Building an MCP Server for Live Market Data: What We Learned

By SNACS Trade ยท 2026-08-21T18:00:04.785640+00:00

Lessons from building and shipping a production remote MCP server for stock market data: tool design, auth, rate limits, point-in-time queries, and registry listings.

We just shipped mcp.snacs.trade, a remote MCP server that gives AI assistants live access to SEC dilution data, market snapshots, and 22 years of price history. It sits on the same engine as our trading platform. Here is what we learned taking an internal data engine to a public MCP surface, in the order we learned it.

Design tools around workflows, not endpoints

Our REST API has dozens of routes. The MCP server exposes 14 tools. That asymmetry is the point: an LLM picking from 40 near-duplicate endpoints wastes context and picks wrong, while 14 tools named for intents (snacs_dilution_get, snacs_dilution_asof_get, snacs_screener_list) map cleanly onto the questions people actually ask an assistant. Each tool wraps what would be 2-3 REST calls into one round trip, because every tool call an agent makes costs latency and tokens.

The single most valuable tool was the one we almost didn't build: point-in-time "as-of" state. Assistants get asked backtesting questions constantly, and answering "what was the float on 2024-12-31" with today's number is silently wrong. Making no-lookahead the contract of one dedicated tool beats hoping the model composes date filters correctly.

Metadata is UX (and it is scored)

MCP clients and registries read more of your schema than a human ever will. Three things measurably improved how assistants used the server:

  1. Parameter descriptions on every param (Annotated[str, Field(description=...)] in FastMCP). Before this, models guessed ticker formats and date shapes; after, retries dropped.
  2. Tool annotations: readOnlyHint: true and openWorldHint: false on all 14 tools tell clients no tool mutates anything, which changes how agent frameworks gate confirmation prompts.
  3. The 100-character description cap in the official registry forces the elevator pitch. Write it early; it clarifies the whole tool list.

Remote-first beats local install

We ship no npm package and no Docker image for the server itself. It is one HTTPS endpoint; Claude Desktop, Claude Code, Cursor, and VS Code all speak streamable HTTP with a bearer header now. That removes the entire "works on my machine" support surface, and it means the server version is always current. The tradeoff is that you own uptime and auth.

Auth: meet clients where they are

Every client sends credentials slightly differently. We accept Authorization: Bearer <key> natively and added a tiny ASGI middleware that promotes an X-API-Key header to a bearer credential when no Authorization header is present, because several MCP gateways and API tools default to X-API-Key. Same key, same verification path, one less support thread.

Rate limiting runs per user, not per surface: MCP calls and REST calls draw from the same bucket (50/min or 1,000/min by plan). An agent that fans out tool calls learns the limit from a structured message inside the tool result, which models handle gracefully by backing off.

OAuth 2.1 shipped alongside this launch (self-hosted Ory Hydra as the authorization server: PKCE S256, dynamic client registration, audience-bound JWTs) - it is what makes the one-click claude.ai connector work. Bearer keys stay, because scripts and CI do not want a browser dance.

Registry listing is its own project

The official MCP registry wants a reverse-DNS namespace (trade.snacs/snacs-data) proven by domain auth: an ed25519 public key served from /.well-known/mcp-registry-auth on the domain, SPF-style. The mcp-publisher CLI handles the dance. Beyond the official registry there is a whole shelf of secondary surfaces (Smithery, Glama, PulseMCP, awesome lists) and they each read your server.json and README differently. Keep one canonical README with the tool table and point everything at it.

What we would tell you to do

  1. Curate tools aggressively; 10-15 intent-named tools beat mirroring your API.
  2. Build the point-in-time tool if your domain has any time dimension at all.
  3. Describe every parameter. Annotate read-only. Treat schema as UX.
  4. Go remote HTTP unless your data is local by nature.
  5. Accept the auth header your users' tools actually send.
  6. Budget a real day for registry listings; the long tail of surfaces is where discovery happens.

The server is live at https://mcp.snacs.trade (14 tools, docs at data.snacs.trade/docs, configs on GitHub). If you are building an MCP server for your own data engine and hit something we did not cover, the comments are open.

Start Free Trial

5 trading day free trial on Edge. Cancel anytime before your trial ends to avoid being charged.