SSD Nodes Learn Hosting plans →
Guides Matt ConnorBy Matt Connor

A free market data MCP server for Claude

Connect Claude to real US market data in five minutes with a no key MCP server: the four read only tools, and what each client needs to talk to it.

What this free market data MCP server does

Strasmore runs a free market data MCP server at https://ai.strasmore.com/mcp, and any MCP client can point at it with no key and no signup. MCP (model context protocol) is the standard that lets a model call tools on a remote server. With this one connected, Claude answers a question from real US market data in the middle of a conversation instead of answering from memory.

Disclosure: Strasmore is built by our team, so this guide uses our own service as the worked example, the same as the guide to running finance analysis with Claude. Every command, limit and error string below was read from the live server and its published documentation on 30 September 2026. None of this is financial advice.

Behind the server is a ClickHouse database called global_markets holding 36 tables: daily and minute bars, dividends, splits, income statements, balance sheets, SEC filings, short interest, IPOs, news, and macro series such as treasury yields and inflation. The model writes read-only SQL against it and reads back rows.

The four tools, and the order a model should use them

The server exposes four tools. All four are read-only and idempotent, so a client can retry any of them safely.

  • list_tables lists every table in the warehouse. It takes no parameters.
  • describe_table takes one table name, for example stocks_daily_aggs, and returns that table's columns with their ClickHouse types plus notes on each column.
  • run_sql takes one sql string and runs a single read-only SELECT against global_markets.
  • get_plans reports what the no-key access includes, and what a free account and each paid plan add on top.

The order matters because a model that guesses column names writes SQL that fails. Have it call list_tables first, then describe_table on the one or two tables it chose, then run_sql. Keep get_plans for the moment a result says it met a limit, because the answer names the plan that lifts it. Most clients follow that order on their own once the tool descriptions are in context. If yours writes SQL immediately and gets a column error, put the order in the prompt: list the tables, describe the one you need, then write the query.

Connect Claude Code

One command adds it as a remote HTTP server.

claude mcp add --transport http strasmore https://ai.strasmore.com/mcp

That registers the server at local scope, which means this project only. Add --scope user to get it in every project, or --scope project to write it into a .mcp.json your teammates share. Check the result:

claude mcp list

A healthy entry prints ✔ Connected. Inside a session, /mcp shows the same status and lets you browse the tools. ✘ Failed to connect on a URL you typed by hand usually means a missing /mcp path, because the host on its own serves the website, not the protocol.

Connect Claude Desktop or claude.ai

Both use the same custom connector flow. Open Settings, then Connectors, then Add custom connector. Name it Strasmore, paste https://ai.strasmore.com/mcp, and leave the authentication fields empty, which is what Strasmore's own connect instructions tell you to do. On claude.ai the same screen sits at Customize, then Connectors, then the plus button.

Custom connectors are available on the Free, Pro, Max, Team and Enterprise plans, and Free is limited to one custom connector. You do need to be signed in to Claude, since that is where the connector lives. Strasmore asks for nothing at this URL.

The connector dialog has no field for a custom header. Its advanced settings cover an OAuth client ID and secret, so this flow cannot carry an Authorization header and cannot expand an environment variable. That matters later, when you add a key.

Connect Cursor

Cursor reads .cursor/mcp.json in the project root, or ~/.cursor/mcp.json for every project.

{
  "mcpServers": {
    "strasmore": {
      "url": "https://ai.strasmore.com/mcp"
    }
  }
}

Cursor supports interpolation in the url and headers fields with the ${env:NAME} form, which is how a key gets in without being written down. VS Code uses .vscode/mcp.json with a servers key and "type": "http" instead.

Run it from an agent on a VPS

A headless agent needs the server config as a file, because there is nobody to click a dialog. Write one, then pass it to a print-mode run.

cat > ~/mcp-strasmore.json <<'JSON'
{ "mcpServers": { "strasmore": { "type": "http", "url": "https://ai.strasmore.com/mcp" } } }
JSON

claude -p --strict-mcp-config --mcp-config ~/mcp-strasmore.json \
  --allowedTools "mcp__strasmore__list_tables" "mcp__strasmore__describe_table" "mcp__strasmore__run_sql" \
  "Which liquid US stocks moved the most in the latest regular session?"

--strict-mcp-config tells Claude Code to ignore every other MCP configuration on the box, so a cron job cannot pick up a server you added for something else. --allowedTools names the three tools that may run without a prompt, since an unattended run has no way to answer one. If the command hangs at startup, the server has not connected yet: Claude Code waits up to the 30 second MCP_TIMEOUT before the first turn. Running this inside a long-lived terminal session is the comfortable way to watch it, and keeping Claude Code alive in tmux on a VPS covers that setup.

One short session, start to finish

Ask a plain question:

Which liquid US stocks moved the most in the latest regular session?

The model calls list_tables, sees stocks_daily_aggs among the 36 names, then calls describe_table with that table and gets back the columns: ticker, date, open, close, high, low, volume, vwap, transactions, otc. Then it calls run_sql with something close to this:

SELECT ticker,
       round(100 * (close - open) / open, 2) AS pct_move,
       volume
FROM global_markets.stocks_daily_aggs
WHERE date = (SELECT max(date) FROM global_markets.stocks_daily_aggs)
  AND volume > 5000000
ORDER BY abs(pct_move) DESC
LIMIT 20

The answer comes back as a list of tickers with their percent move and volume, and the model explains it in a sentence. Read the SQL before you trust the answer, because the filter is the analysis: volume > 5000000 is what the word "liquid" meant here, and you chose neither that threshold nor the session it picked. Every result also states which limit it met and which plan lifts that limit, so a truncated answer says so rather than looking complete.

Add a free API key when the no-key surface runs out

Create a key in the terminal at https://ai.strasmore.com, in the API keys section. The key is shown once, because the service stores only its SHA-256 hash and cannot print it again. Keys start with sk_live_ and belong to an organisation, so making a second key does not raise your rate limit.

Send it as an Authorization: Bearer header to the account endpoint, which is the same server running at your plan:

claude mcp add --transport http strasmore-account \
  https://ai.strasmore.com/mcp/account \
  --header "Authorization: Bearer $STRASMORE_API_KEY"

That command has a trap worth knowing. The shell expands $STRASMORE_API_KEY before claude ever sees it, so the resolved secret is written into the config file. For a config that goes into git, use a project .mcp.json and let the client expand it at load time instead:

{
  "mcpServers": {
    "strasmore-account": {
      "type": "http",
      "url": "https://ai.strasmore.com/mcp/account",
      "headers": {
        "Authorization": "Bearer ${STRASMORE_API_KEY}"
      }
    }
  }
}

Claude Code expands ${VAR} and ${VAR:-default} in .mcp.json. Cursor does the same with ${env:NAME} in url and headers. The claude.ai and Claude Desktop connector dialog does neither, so on those two use OAuth at the account URL and keep the raw key out of it. Export the value in your shell profile or a file the repository ignores, never in the committed config, which is the same rule for keeping secrets out of the agents you run.

An invalid or revoked key is an error, not a downgrade. The service answers 401 with Invalid or revoked API key. and stops. It never falls back to the no-key tier, so a typo in your header shows up as a failure you can see rather than as quietly shallower data.

What each tier allows, in numbers

Without a key the server allows 500 rows and 20 seconds per query, with history from 1 January 2025. A free account, which needs no card, adds a daily budget of 100 queries at 10 requests per minute. The keyed HTTP API documents a 20,000 row cap, where a larger result is truncated with a truncated flag rather than refused, and a 60 second server-side query timeout.

These are the published plan figures, read from Strasmore's pricing page on 30 September 2026.

ChartStrasmore published plan limits, 30 September 2026
The data behind this chart
[
  {
    "plan": "Free",
    "price_usd_month": 0,
    "requests_per_minute": 10,
    "equity_history_years": 1
  },
  {
    "plan": "Developer",
    "price_usd_month": 79,
    "requests_per_minute": 60,
    "equity_history_years": 3
  },
  {
    "plan": "Pro",
    "price_usd_month": 249,
    "requests_per_minute": 600,
    "equity_history_years": 22
  }
]

Free costs 0 and allows 10 requests per minute over one year of history. Developer is 79 dollars a month for 60 requests per minute and 3 years. Pro is 249 dollars a month at 600 requests per minute, with full history: 22 years of equities and 12 years of options. Enterprise is priced on request and runs as your own instance. History windows cover whole calendar years and move on 1 January.

Five tables sit behind a paid plan: stocks_trades, options_trades, options_greeks, cache_stocks_quotes and cache_options_quotes. Everything else, the bars, fundamentals, filings, corporate actions and macro series, answers on the free surface. The NBBO (national best bid and offer) quote tapes are open for the last five days.

The errors a limit produces

The keyed API returns JSON carrying a detail message, a stable error_code and a request_id, and the MCP tool surfaces the same conditions in the tool result. Learn these four:

  • 400 means the SQL was rejected by the gate, or the column does not exist. Call describe_table and write the query again.
  • 401 with Invalid or revoked API key. means the header is wrong. Check for a missing Bearer prefix or an unexpanded variable.
  • 402 with HISTORY_WINDOW_EXCEEDED means every date you asked for sits before your plan's window. Narrow the date range, or upgrade.
  • 429 with RATE_LIMITED or DAILY_QUOTA_EXCEEDED means you passed 10 requests per minute or 100 queries per day on the free plan. The response carries a Retry-After header giving the seconds to wait.

A 503 with WAREHOUSE_UNREACHABLE is the service's own problem, so retry rather than rewrite your query.

Why this server needs no session

Every tool here takes its whole input as an argument and returns the answer in one response, so the server keeps nothing between calls. That is what lets it run behind plain HTTP with no login, and it is why a retry after a timeout is safe: a stateless MCP server holds no session to lose.

If you want the same shape for your own data, the pattern is small: a read-only database, a handful of narrow tools, one endpoint. Running your own MCP servers on a VPS walks through hosting one, and the comparison of skills, MCP servers and rules files is worth reading first, because plenty of things people build as an MCP server are better off as a skill.

FAQ

Do I need an account to use the Strasmore MCP server?

No. The endpoint at https://ai.strasmore.com/mcp takes no key and no signup, and the free surface covers 36 tables at 500 rows and 20 seconds per query with history from 1 January 2025. You do need an account with your MCP client itself, so a claude.ai custom connector means signing in to Claude, and Free plan users there may add one custom connector.

What happens if I send an invalid API key?

The request fails with HTTP 401 and the message Invalid or revoked API key.. There is no silent downgrade to the no-key tier, which is the behaviour you want, because a key that quietly stopped working would give you shallower answers that still look correct. If you see this after a claude mcp add, check that your shell variable was set when you ran the command.

Which tables need a paid plan?

stocks_trades, options_trades, options_greeks, cache_stocks_quotes and cache_options_quotes. These are the tick tape, the full quote tape and the options greeks. Daily and minute bars, dividends, splits, income statements, balance sheets, SEC filings, short interest, IPOs, news and macro series all answer without a paid plan, inside your plan's history window.

Why did my query return only 500 rows?

That is the no-key row cap. The result states the limit it met and names the plan that lifts it, so read the note rather than assuming the data ended. On a keyed plan the cap is 20,000 rows and the result is truncated with a truncated flag rather than refused, so check that flag before you treat a result as complete. Adding a tighter WHERE clause or an aggregate is usually better than raising the cap.