Connect as an MCP server
The remote Streamable HTTP MCP server exposes the same contract as the REST API — search, profiles, emails, price estimates, account status, and durable jobs — so any MCP-capable agent can use Stormy as a tool.
Claude Code
Export the key in the same shell first. $STORMY_API_KEY is expanded by your shell at the moment you connect. Paste the command without it and the header is stored as the literal eleven characters, so every call answers 401 Invalid or revoked Stormy API key with a valid key in your clipboard.
export STORMY_API_KEY=stm_live_...
claude mcp add --transport http stormy https://stormy.ai/mcp \
--header "Authorization: Bearer $STORMY_API_KEY"Claude Desktop, Cursor, Windsurf, VS Code — any mcpServers client
Not everyone is in a terminal. Any client that reads an mcpServers block takes the config below. In Claude Desktop it goes in Settings → Developer → Edit Config; in Cursor it is ~/.cursor/mcp.json; in a repo it is .mcp.json. Restart the app afterwards.
{
"mcpServers": {
"stormy": {
"url": "https://stormy.ai/mcp",
"headers": { "Authorization": "Bearer stm_live_YOUR_KEY_HERE" }
}
}
}Put the key in literally, exactly as shown. A JSON file is not a shell and will not expand $STORMY_API_KEY. Stormy does not yet support the one-click OAuth connector flow, so a header is the way in.
Codex
[mcp_servers.stormy]
url = "https://stormy.ai/mcp"
bearer_token_env_var = "STORMY_API_KEY"Claude Agent SDK
from claude_agent_sdk import ClaudeAgentOptions, ClaudeSDKClient
import os
options = ClaudeAgentOptions(
mcp_servers={
"stormy": {
"type": "http",
"url": "https://stormy.ai/mcp",
"headers": {"Authorization": f"Bearer {os.environ['STORMY_API_KEY']}"},
}
},
)
async with ClaudeSDKClient(options=options) as agent:
await agent.query("Find 25 cached YouTube roofing creators.")
async for message in agent.receive_response():
print(message)How long a call takes
search_people takes 45–90 seconds. It fetches and reads real profiles and judges each one against your request; there is no cached shortcut that skips the reading. Past 100 seconds it stops holding the connection and returns a job_id with poll_after_seconds instead.
lookup_profile 1–5s cached · find_emails up to 90s for a batch of 25 · a discover_creators job 30–60s. A search is not hung at 60 seconds — retrying it pays twice.
Tools
search_peopleplatform · query · limit · fresh · min_followers · max_followersFind people from a plain-language query. Every result is judged against what you asked for and carries its score and reason. Use min/max_followers to ask for accounts your own size rather than the biggest in the niche.
lookup_profiletarget · platform · fresh · include_postsResolve a URL, handle, or channel ID into one normalized profile.
get_video_transcripturl · languageEverything said in a YouTube video, as text, captions or transcribed audio.
find_emailsplatform · targets[1..25]Verified email enrichment. Bills only successful finds.
estimate_pricequantity · include_emailQuote the exact rate card before a large call.
account_status—Entitlements, remaining prepaid usage, and top-up URL.
describe_social_data—The machine-readable platform, field, pricing and workflow contract.
start_social_joboperation · arguments · idempotency_keyQueue durable work. Operations: search_people, lookup_profile, find_emails, discover_creators.
get_social_jobjob_idStatus, progress, results, and the exact time to poll again.
list_social_jobsstatus · limitRecover prior work instead of submitting a duplicate.
cancel_social_jobjob_idStop a job before a worker starts it.
Durable jobs and discover_creators
start_social_job also accepts discover_creators, the deeper creator search. It writes and expands its own queries, judges every profile, and is the operation that takes an audience band, an engagement floor and an account-type filter — the shape of "find me people my size who would post about this". It counts with target_count, not limit, and an argument name it does not recognise is rejected rather than silently dropped.
{
"operation": "discover_creators",
"arguments": {
"platform": "instagram",
"query": "creators who post about handmade jewellery",
"target_count": 10,
"max_followers": 50000,
"exclude_business": true,
"max_spend_usd": 2.00
}
}Agent execution policy
Any people search → a durable job, or a direct search_people call if you can wait 45–90 seconds; both run the same engine. A single known profile → lookup_profile. Estimate when the user asks about cost or wants 25+ paid results. Honor poll_after_seconds, split email targets into batches of 25, never infer contacts from search results, and never resubmit a nonterminal job. Read warnings on a short result before retrying — it says whether the niche was thin or whether part of the search did not answer.
Machine-readable contract: capabilities JSON · OpenAPI · llms.txt