본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 20. 12:11

모든 AI 어시스턴트에게 실시간 NSE + BSE 주식 데이터를 제공하는 오픈 소스 MCP 서버를 구축했습니다

요약

AI 어시스턴트가 실시간 NSE 및 BSE 주식 데이터를 조회할 수 있도록 돕는 오픈 소스 MCP 서버를 구축했습니다. Cloudflare Workers를 활용한 서버리스 아키텍처를 통해 복잡한 설치 없이 URL만으로 즉시 사용 가능한 환경을 제공합니다.

핵심 포인트

  • Model Context Protocol(MCP)을 활용해 AI의 실시간 데이터 접근성 문제 해결
  • NSE 및 BSE의 약 8,200개 주식에 대한 34가지 분석 도구 제공
  • Cloudflare Workers 기반의 Stateless 아키텍처로 배포 편의성 극대화
  • Claude, ChatGPT, Cursor 등 다양한 AI 모델과 호환 가능

갈증

ChatGPT나 Claude에게 "지난 분기 Reliance의 영업 이익률(operating margin)은 얼마였나요?"라고 물어보면 두 가지 답변 중 하나를 듣게 됩니다. "실시간 데이터가 없습니다"라는 정중한 답변이거나, 확신에 찬 틀린 숫자입니다. 추론 능력은 훌륭하지만 데이터 접근성이 전혀 없습니다. 이 모델들은 학습 데이터 컷오프(training cut-off) 이후의 모든 것에 대해 눈이 멀어 있으며, NSE/BSE에 대한 네이티브한 창구도 전혀 가지고 있지 않습니다.

그래서 이를 해결하기 위해 MCP 서버를 구축하고 오픈 소스로 공개했습니다. 이것은 구축 이야기이자, 여러분의 환경에 직접 연결하고 싶을 경우를 위한 빠른 시작 가이드입니다.

30초 MCP 복습

**Model Context Protocol (MCP)**는 AI 어시스턴트가 일관된 인터페이스를 통해 외부 도구를 호출할 수 있게 해주는 개방형 표준입니다. 모델이 추측하는 대신, RELIANCE에 대해 get_stock_quote와 같은 구조화된 요청을 보내고, 실제 데이터를 받아와서 이를 바탕으로 추론합니다. 하나의 프로토콜만 있으면 Claude, ChatGPT, Cursor, Gemini, Grok 모두 동일한 데이터 소스에 접속할 수 있습니다.

기본적으로 AI 도구를 위한 USB-C라고 할 수 있습니다.

공개한 기능: 34가지 도구

search_stocks            screen_stocks (326 fundamental filters)
screen_stocks_technical  get_company_profile   get_financials
get_stock_quote          get_price_history     get_shareholding
...

범위: 약 8,200개의 모든 NSE + BSE 주식, 기본적 분석(fundamentals), 기술적 분석(technicals), 기관 흐름(institutional flows), 시장 데이터 및 포트폴리오 추적을 포함합니다. (이것은 리서치 도구이지 브로커가 아닙니다. 즉, 거래를 실행하지는 않습니다.)

아키텍처 결정

가장 중요한 결정: 리모트 퍼스트(remote-first), 엣지(on the edge) 기반.

┌─────────────────┐   JSON-RPC / HTTPS   ┌──────────────────────┐
│  AI Assistant   │ ───────────────────► │  Cloudflare Worker   │
│ (Claude, etc.)  │ ◄─────────────────── │  (stateless MCP)     │
...

대부분의 MCP 서버는 직접 설치하고 실행해야 하는 로컬 stdio 프로세스로 배포됩니다. 이는 개발자가 아닌 사람들에게는 마찰(friction)의 벽이 됩니다. 저는 누군가가 claude.ai에 URL 하나만 붙여넣으면 바로 끝낼 수 있기를 원했습니다. 그래서 서버를 Cloudflare Worker에서 실행되도록 했습니다. 전 세계적으로 분산되어 있으며, 관리해야 할 서버도 없습니다.

상태 비저장 전송 (Stateless transport)

MCP SDK의 WebStandardStreamableHTTPServerTransport는 상태 비저장 (stateless) 모드에서 Workers와 완벽하게 매핑됩니다. 즉, 어떤 요청이든 어떤 에지 (edge) 위치로 들어오더라도 동일하게 처리됩니다.

const server = createServer(env, ph, userId);
const transport = new WebStandardStreamableHTTPServerTransport({
  sessionIdGenerator: undefined,  // stateless
...

인증 (Auth)이 가장 어려운 부분이었습니다

MCP 클라이언트는 매우 다양합니다. 채팅 앱 (Claude.ai, ChatGPT)은 동적 클라이언트 등록 (Dynamic Client Registration, RFC 7591) 및 디스커버리 엔드포인트 (discovery endpoints, RFC 8414, RFC 9728)를 포함한 전체 OAuth 흐름을 기대합니다. 반면 코드 에디터는 단순히 베어러 토큰 (bearer token)만을 원하는 경우가 많습니다.

OAuth 핸드셰이크 (handshake)가 "그냥 작동하게" 만드는 비결은 다음과 같습니다. 첫 번째 initialize 요청 시 WWW-Authenticate 헤더와 함께 401 응답을 반환하는 것입니다. 이것이 클라이언트의 내장된 OAuth 흐름을 시작하는 신호가 됩니다.

if (!authHeader?.startsWith("Bearer ") && !isPublicMethod) {
  return Response.json(
    { error: "authentication_required" },
...

따라서 서버는 짧은 수명의 HMAC 액세스 토큰 (access tokens)과 접두사(tpt_rt_…)로 구분되는 긴 수명의 개인용 토큰 (personal tokens)을 모두 수용합니다. 하나의 인증 접점 (auth surface)에 두 가지 자격 증명 (credential) 유형이 있는 셈입니다. tools/listping은 공개 상태로 유지하여, 레지스트리 (registries)가 인증 없이도 카탈로그를 발견할 수 있도록 했습니다.

선량한 사용자를 처벌하지 않는 속도 제한 (Rate limiting)

두 개의 독립적인 계층을 사용합니다:

  1. 분당 버스트 스무더 (Per-minute burst smoother) (KV, fails open 방식) — 단일 토큰이 하루 할당량을 몇 초 만에 모두 쏟아붓는 것을 방지합니다. 만약 KV에 문제가 생기면 요청을 허용합니다. 실제 상한선은 일일 쿼터 (daily cap)이기 때문입니다.
  2. 일간/월간 쿼터 (Daily/monthly quota) (D1, fails closed 방식) — 도구 (tool)가 실행되기 _전_에 원자적 UPSERT를 통해 단위를 예약합니다. 제한기 (limiter)에 접근할 수 없으면 → 거부합니다. 측정되지 않은 접근 권한을 절대 부여하지 않습니다.

가장 만족스러운 부분은 실패한 호출은 환불된다는 점입니다. MCP SDK는 도구 인자 (tool argument)가 스키마 검증 (schema validation)에 실패할 때마다 InvalidParams를 발생시키는데, LLM은 인자를 잘못 생성하는 환각 (hallucination)을 끊임없이 일으킵니다. 모델이 인자를 잘못 입력했다는 이유로 사용자의 쿼터를 차감하는 것은 매우 화가 나는 일일 것입니다.

if (quotaConsumed && userId) {
  quotaConsumed = false;            // 이중 환불 방지
  if (hasError) {
...

npm 패키지는 단순한 브릿지(bridge)일 뿐입니다

stdio 전용 클라이언트(stdio-only clients)를 위한 아주 작은 npm 패키지가 있습니다. 약 300줄 규모이며, 런타임 의존성(runtime deps)이 전혀 없습니다. 비즈니스 로직은 포함되어 있지 않습니다. 이 패키지는 stdin으로부터 JSON-RPC를 읽어 HTTPS를 통해 Worker로 전달하고, 응답을 stdout에 작성합니다. 또한 메시지 프레이밍(message framing, 클라이언트마다 다른 Content-Length 방식과 newline-delimited JSON 방식)을 자동으로 감지하며, 액세스 토큰(access token)이 만료되기 전에 갱신합니다. 모든 도구(tool) 로직은 서버에 존재하므로, 누군가 npm update를 실행할 필요 없이 새로운 도구가 즉시 배포됩니다.

빠른 시작 (Quick start)

설치 불필요 (claude.ai, ChatGPT, Gemini, Grok) — URL을 붙여넣고 Google로 로그인하세요:

npm을 통한 로컬 실행 (Cursor, Windsurf, Claude Desktop):

{
  "mcpServers": {
    "tapetide": {
...

그 다음 다음과 같이 질문해 보세요:

"지난 분기에 FII 보유 비중이 상승하고, ROE가 15% 이상이며, RSI가 40 미만인 중형주(mid-caps)를 찾아줘."

직접 MCP 서버를 구축할 때 얻은 교훈

  • 사용자가 모두 개발자가 아니라면 원격(remote) 방식을 사용하세요. 도달 범위 측면에서는 npx 명령보다 붙여넣기 가능한 URL이 훨씬 유리합니다.
  • Stateless(무상태) + edge(엣지) 조합은 MCP의 요청/응답(request/response) 구조에 자연스럽게 부합합니다.
  • OAuth + DCR을 위한 실시간 시간을 확보하세요. 이 부분은 가장 화려하지 않으면서도 가장 취약한 부분입니다. .well-known 디스커버리 엔드포인트(discovery endpoints)를 정확하게 구현해야 합니다.
  • 한 가지 이상의 인증 유형(credential type)을 지원하세요. 채팅 앱과 에디터는 서로 다른 것을 요구합니다.
  • 오류 발생 시 쿼터(quota)를 환불하세요. LLM은 항상 잘못된 도구 호출(tool calls)을 합니다. 사용자가 그 비용을 지불하게 하지 마세요.

MIT 라이선스 하에 무료 및 오픈 소스로 제공됩니다. 소스 코드, 34개의 모든 도구, 그리고 설정 가이드는 다음에서 확인하세요:

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

이것을 기반으로 무언가를 구축하시거나 원하는 도구에 대한 아이디어가 있다면, 댓글로 알려주시면 감사하겠습니다.

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0