Introducing

Query Market, Fundamental, and Alternative Data across financial markets with the updated Massive MCP server

Mar 30, 2026

TL;DR: The Massive MCP server rewrite collapses everything into 4 composable tools (search, read docs, call API, query with SQL) with 11 total parameters, cutting context overhead by over 90%. The server also ships with built-in financial functions: Black-Scholes Greeks, Sharpe/Sortino ratios, & moving averages.


In this post, we'll walk through our rebuilt MCP server for Massive's financial data API: what changed, why we rewrote it, and how to set it up so your AI agent can discover, call, and query accurate, real-time market data on its own.

The server is also available as an Integration on Claude Desktop, so you can connect it without touching a config file.

Why we rewrote the MCP server

The original Massive MCP server exposed one tool per API endpoint. That made sense early on, but as the platform grew, the tool count hit 53.

This is extremely inefficient, because every tool definition (name, description, input schema) gets injected into the model's context window on every single request. Anthropic's engineering team documented this in their Advanced Tool Use guide: in a real-world setup with ~58 tools across five MCP servers, tool definitions alone consumed roughly 55,000 tokens before the conversation even started. They observed internal setups where tool definitions hit 134,000 tokens. That's context window space that could be holding your actual conversation, your data, your analysis.

Our 53-tool server had the same problem. Each Massive endpoint had its own tool with a full parameter schema. Some of the heavier tools, like our Benzinga earnings endpoint, carried upwards of 45 parameters each with types, descriptions, and filter variants. Across all 53 tools, the server exposed roughly 450 parameters total. Based on Anthropic's published benchmarks for similar tool sets, we estimate this loaded somewhere in the range of 15,000-25,000 tokens per session, just for tool definitions. That's tokens you're paying for on every request, and context space the model can't use for reasoning about your actual question.

The rewrite compresses everything into four composable tools with 11 total parameters. Based on the same benchmarks, total tool definition overhead drops to roughly 1,000-1,500 tokens. That's an estimated reduction of over 90%.

But the token savings are only half the story. Anthropic's research also showed that tool selection accuracy degrades as tool count increases. With 50+ tools, the model has to read through dozens of schemas to pick the right one. Their testing showed that Opus 4 improved from 49% to 74% tool selection accuracy when using search-based discovery instead of a flat tool list. Fewer, well-designed tools means the model picks the right action more reliably.

The new architecture also solves the maintenance problem. When we shipped a new endpoint under the old design, we had to add a new tool definition, update the server, and push a new version. Now, the server indexes endpoints dynamically from our documentation at startup. New endpoints are discoverable the next time the server restarts. No code changes, no version bumps.

The four tools

Here's what the new server exposes:

search_endpoints

Search for API endpoints and built-in financial functions by natural language query. The server indexes every Massive REST endpoint at startup using BM25 ranking over the documentation served at massive.com/docs/rest/llms.txt. When you ask your agent for "AAPL aggregate data," it runs a relevance search and returns matching endpoint names, URL patterns, and descriptions. You can scope the search to endpoints only, built-in functions only, or both.

get_endpoint_docs

Once the agent identifies a relevant endpoint from the search results, it fetches the full parameter documentation: path parameters, query parameters, types, defaults, and constraints. This is the equivalent of the agent reading the docs page for a specific endpoint, except it happens programmatically and only for what's needed.

call_api

Call any Massive REST API endpoint. The agent constructs the request from the parameter docs it just read, and the server handles authentication, pagination hints, and response parsing. The key feature here is the

store_as
parameter: pass a table name and the response gets stored as an in-memory DataFrame. You can also pass an
apply
parameter to run built-in financial functions on the results inline, without a separate tool call.

query_data

Run SQL against stored DataFrames using an embedded SQLite engine. This supports everything you'd expect: JOINs, CTEs, window functions, aggregations. It also supports utility commands like

SHOW TABLES
,
DESCRIBE <table>
, and
DROP TABLE
. If your agent fetched AAPL daily bars and stored them as "aapl_bars," you can immediately run queries like:

SELECT date, close, close - LAG(close) OVER (ORDER BY date) AS daily_change
FROM aapl_bars
ORDER BY date DESC
LIMIT 10

The result can also be post-processed with the

apply
parameter, so you can chain a moving average or returns calculation directly onto a SQL result.

This four-tool pattern mirrors the approach Anthropic recommends in their tool use documentation: instead of giving the model a massive catalog of narrow tools, give it a small set of composable primitives that it can chain together. The model becomes a better tool user when it has fewer, more flexible tools to reason about.

Token usage: before and after

To make this concrete, here's the actual structural difference between the old and new server schemas.

Old server (v0.7.1, 53 tools)

Each tool carried a name, description, and full JSON Schema for its input parameters. The schemas ranged from lightweight (

get_last_trade
with 1 parameter) to heavy (
list_benzinga_earnings
with 45 parameters,
list_benzinga_guidance
with another 45,
list_benzinga_ratings
with 37). Across all 53 tools, the server defined roughly 450 individual parameters with types, descriptions, and filter variants.

Based on Anthropic's published tool token benchmarks, where comparable tool sets (58 tools across five servers) consumed ~55,000 tokens, we estimate our 53 tools loaded approximately 15,000-25,000 tokens per session. The range depends on how the MCP client serializes the schemas, but the structural data is clear: 53 tool names, 53 descriptions, 53 JSON Schemas, ~450 parameters.

New server (v0.8.0+, 4 tools)

Four tools with a total of 11 parameters.

search_endpoints
takes a query string and an optional scope enum.
get_endpoint_docs
takes a single URL string.
call_api
takes a method, path, params object, and optional
store_as
,
apply
, and
api_key
fields.
query_data
takes a SQL string and optional
apply
. The descriptions are longer than the old per-tool descriptions (they include usage guidance), but the total schema surface is dramatically smaller. We estimate roughly 1,000-1,500 tokens for all four tool definitions combined.

The server also includes a short

instructions
string that tells the model when to use these tools, adding another ~100-130 tokens. Even with that, the total overhead is a fraction of the old design.

Why this matters for cost

Anthropic charges for tool definition tokens as input tokens on every request. If you're running a multi-turn conversation with 20 back-and-forth exchanges, you're paying for those tool definition tokens 20 times. The difference between ~20,000 tokens and ~1,200 tokens of overhead, multiplied across every turn, adds up fast.

Old server (v0.7.1)New server (v0.8.0+)
Tools534
Total parameters~45011
Estimated token overhead15,000-25,0001,000-1,500
New endpoint supportManual tool addition + releaseAutomatic at startup

How the search index works

At startup, the server fetches the llms.txt index from Massive's documentation site. This index lists every REST endpoint with its name, URL pattern, and a short description. The server tokenizes these entries and builds a BM25 index in memory.

When the agent calls

search_endpoints
with a natural language query, the server ranks every endpoint by relevance and returns the top matches. Because the index is rebuilt on each startup, any new endpoints that Massive ships are immediately discoverable without updating the MCP server itself.

This is the core architectural decision that makes the four-tool design work. The agent doesn't need to know about every endpoint in advance. It searches, finds what's relevant, reads the docs for just that endpoint, and calls it. Context usage stays minimal.

If you've read Anthropic's documentation on tool search patterns, this will look familiar. Their recommended approach for scaling beyond a handful of tools is to replace static tool catalogs with search-based discovery. We've baked that pattern directly into the server itself, so you don't have to implement it in your client.

Built-in financial functions

The server ships with 13 built-in financial functions that can be applied to API results or SQL query outputs via the

apply
parameter. These run server-side, so the agent doesn't need to write Python or import libraries.

Options Greeks (Black-Scholes)

bs_price
,
bs_delta
,
bs_gamma
,
bs_theta
,
bs_vega
,
bs_rho

These compute standard Black-Scholes values. Useful when you're working with raw options chain data and need Greeks that aren't included in the snapshot, or when you want to recalculate under different assumptions.

Returns analysis

simple_return
,
log_return
,
cumulative_return
,
sharpe_ratio
,
sortino_ratio

Run these against stored price series to get return metrics without exporting the data or writing calculation code.

Technical indicators

sma
(simple moving average),
ema
(exponential moving average)

Apply these directly to OHLCV data stored from aggregate bar queries.

The pattern looks like this in practice: call the API to fetch daily bars, store them as a table, then run a SQL query with

apply: "sma(close, 20)"
to get a 20-day moving average column appended to your results.

In-memory data storage

The server maintains an in-memory table store backed by pandas DataFrames. When you use the

store_as
parameter on a
call_api
or
query_data
call, results are saved under the name you provide. This lets you build up a working dataset across multiple API calls and then query across all of them with SQL.

There are configurable limits to keep memory usage predictable:

VariableDefaultDescription
MASSIVE_MAX_TABLES
50Maximum number of stored tables
MASSIVE_MAX_ROWS
50,000Maximum rows per table

These can be set via environment variables. For most workflows, the defaults are more than sufficient.

Getting started

There are three ways to connect the Massive MCP server, depending on which client you use.

Claude Desktop (Integration)

The fastest option. The Massive MCP server is available as an Integration on Claude Desktop. Go to your Integrations settings, find Massive, and connect. No install, no config file. You'll just need your Massive API key.

Claude Code (CLI)

Install with uv and add it in one command:

uv tool install "mcp_massive @ git+https://github.com/massive-com/mcp_massive@v0.8.3"
claude mcp add massive -e MASSIVE_API_KEY=your_key_here -- mcp_massive

Cursor or other MCP clients

The server supports stdio, SSE, and streamable-http transports. For Cursor, add it to your MCP configuration:

{
  "mcpServers": {
    "massive": {
      "command": "mcp_massive",
      "env": {
        "MASSIVE_API_KEY": "your_key_here"
      }
    }
  }
}

Set the

MCP_TRANSPORT
environment variable if you need SSE or streamable-http.

Requirements:

  • Python 3.12+
  • A Massive API key on any plan
  • uv package manager (recommended) or pip

Configuration

The only required configuration is your API key. Everything else has sensible defaults:

VariableDefaultDescription
MASSIVE_API_KEY
(required)Your Massive API key
MCP_TRANSPORT
stdio
Transport protocol:
stdio
,
sse
, or
streamable-http
MASSIVE_API_BASE_URL
https://api.massive.com
API base URL override
MASSIVE_LLMS_TXT_URL
https://massive.com/docs/rest/llms.txt
Documentation index URL override
MASSIVE_MAX_TABLES
50
Maximum number of in-memory tables
MASSIVE_MAX_ROWS
50000
Maximum rows per table

What a typical session looks like

Once the server is connected, you interact with Massive's API entirely through natural language. Here's what a typical workflow looks like from the agent's perspective:

  • You ask: "Get me the last 30 days of daily AAPL data."
  • The agent calls
    search_endpoints
    with a query like "AAPL daily aggregate bars" and gets back the stocks aggregates endpoint as the top result.
  • The agent calls
    get_endpoint_docs
    to read the parameter schema for that endpoint: path parameters (ticker, multiplier, timespan, from, to), query parameters (sort, limit, adjusted).
  • The agent calls
    call_api
    with the correct path and parameters, and passes
    store_as: "aapl_daily"
    to save the results.
  • You follow up: "What was the average volume on up days vs down days?"
  • The agent calls
    query_data
    with:
SELECT
  CASE WHEN close > open THEN 'up' ELSE 'down' END AS direction,
  ROUND(AVG(volume)) AS avg_volume,
  COUNT(*) AS days
FROM aapl_daily
GROUP BY direction

No manual endpoint lookup. No URL construction. No context window filled with 53 tool schemas. The agent discovers what it needs, fetches only the relevant documentation, and keeps your conversation focused on the analysis.

What's next

The MCP server is open source and under active development. If you run into issues or want to request a feature, open an issue on the repo: github.com/massive-com/mcp_massive

We're particularly interested in feedback on the built-in financial functions. If there are calculations you find yourself running repeatedly after fetching data, those are good candidates for new

apply
functions.

To get started, pick whichever client you prefer, plug in your API key, and ask your agent for the data you need. It'll figure out the rest.

Disclaimer

This content is for educational purposes only. Nothing in this post constitutes investment advice or a recommendation to buy or sell any securities or other financial instruments. Massive is a market data provider, not a broker-dealer, exchange, or investment adviser. Market data accessed through Massive may originate from third-party exchanges and data providers or may be derived or calculated by Massive; in either case, it is subject to the applicable terms of your Massive subscription agreement. The data and code samples provided by Massive are offered on an "as-is" basis without any warranty of accuracy, completeness, or timeliness. You are solely responsible for your use of the data provided by Massive and for compliance with all applicable terms and conditions, laws, and data licensing requirements.

From the blog

See what's happening at Massive