sec-edgar-mcp 免費遠端 MCP 伺服器讓 AI 智能體查詢 SEC EDGAR 資料
Give your AI agent SEC EDGAR data: a free remote MCP server for insider trades and XBRL financials
MonRiah Studio 的 sec-edgar-mcp 是免費、MIT 授權的遠端 MCP 伺服器,提供七項唯讀工具,供 AI 智能體查詢美國 SEC EDGAR 的內幕交易、申報文件及 XBRL 財務資料。
MCP (Model Context Protocol) is an open standard that lets an AI client such as Claude, Cursor or VS Code call external tools through one common interface.
This post walks through a free, MIT-licensed MCP server for U.S. SEC EDGAR data. It runs remotely, so there's nothing to install and no API key. I'll show how to connect it, three real calls with their actual output, how it works inside, and where it falls short.
- Endpoint (Streamable HTTP, no key):
https://sec-edgar-api.kidriahx.workers.dev/mcp - Source: https://github.com/monriah-studio/sec-edgar-mcp-remote
- MCP Registry name:
io.github.monriah-studio/sec-edgar-mcp
Why EDGAR needs a wrapper
EDGAR is one of the best free financial datasets around: every insider trade, 10-K, 8-K and XBRL financial fact that U.S. public companies file. It's also awkward to use, especially for an agent:
- The User-Agent rule. SEC's fair-access policy asks every client to send a declared User-Agent with a contact email and to stay under 10 requests per second. Requests that skip this get 403s. An LLM making fetches on its own won't know that.
-
CIK lookup. Most endpoints want a 10-digit Central Index Key (
0000320193), not a ticker (AAPL). You have to look it up in a roughly 1 MBcompany_tickers.jsonfile first. - Form 4 is XML. Insider trades come as one XML document per filing, full of transaction codes (P, S, A, M, F, G), derivative tables and footnotes.
-
XBRL is messy. The
companyconceptJSON repeats the same period across many filings and mixes 3-month, 9-month and 12-month durations. Getting "net income by fiscal year" out of it means filtering and de-duplicating.
The server does all of this and returns compact JSON.
The seven tools
| Tool | What it returns |
|---|---|
get_insider_trades |
Form 4 transactions for a company or an insider, with buy/sell totals and a 10b5-1 flag |
get_market_insider_buys |
Open-market insider purchases across the market, grouped by company, with cluster-buy detection (2+ insiders) |
get_company_filings |
Latest 10-K, 10-Q, 8-K (with item numbers) and other filings, with document links |
get_company_snapshot |
Revenue, margins, net income, EPS, cash flow, balance sheet and YoY growth from XBRL |
get_company_concept |
Annual or quarterly history of any XBRL tag |
search_filings |
EDGAR full-text search with phrase, form and date filters |
resolve_company |
Ticker ↔ CIK lookup |
Every tool takes a ticker or a CIK, and all of them are marked read-only.
Connect a client
Cursor: add this to ~/.cursor/mcp.json (or .cursor/mcp.json in a project):
{
"mcpServers": {
"sec-edgar": {
"url": "https://sec-edgar-api.kidriahx.workers.dev/mcp"
}
}
}
VS Code (Copilot agent mode): add this to .vscode/mcp.json:
{
"servers": {
"sec-edgar": {
"type": "http",
"url": "https://sec-edgar-api.kidriahx.workers.dev/mcp"
}
}
}
Claude Desktop: on plans that support custom connectors, add the URL under Settings → Connectors. You can also bridge it through claude_desktop_config.json with the mcp-remote package (needs Node.js):
{
"mcpServers": {
"sec-edgar": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://sec-edgar-api.kidriahx.workers.dev/mcp"]
}
}
}
Claude Code: claude mcp add --transport http sec-edgar https://sec-edgar-api.kidriahx.workers.dev/mcp
Then try prompts like "Show NVIDIA's last insider sales and whether they were under 10b5-1 plans" or "Which companies had cluster insider buying this week?"
Three real calls with curl
The server is stateless, so you don't need an SDK to test it. Every request is a single JSON-RPC POST. Start with initialize:
URL=https://sec-edgar-api.kidriahx.workers.dev/mcp
curl -s $URL \
-H 'content-type: application/json' \
-H 'accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"1"}}}'
{"result":{"protocolVersion":"2025-06-18","capabilities":{"tools":{}},"serverInfo":{"name":"sec-edgar-mcp","title":"SEC EDGAR Insider Trades & Financials","version":"1.0.0"}, ...},"jsonrpc":"2.0","id":1}
Each tool result comes back as JSON text in result.content[0].text. The outputs below are pretty-printed and trimmed (...). I ran them on October 23, 2026, so your numbers will differ.
1. NVIDIA insider trades
curl -s $URL -H 'content-type: application/json' -H 'accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"get_insider_trades","arguments":{"ticker_or_cik":"NVDA","filings":5,"max_rows":5}}}'
{
"company": {"id": "NVDA", "cik": "0001045810", "ticker": "NVDA", "name": "NVIDIA CORP"},
"filingsParsed": 5,
"summary": {"transactions": 8, "openMarketBuys": 0, "openMarketSells": 5,
"sellShares": 1396460, "sellValueUsd": 306933627.99, "distinctInsiders": 5},
"returned": 5,
"transactions": [
{"date": "2026-09-21", "insider": "Teter Timothy S.", "role": "EVP, General Counsel and Sec",
"code": "S", "shares": 12483, "price": 222.1932, "valueUsd": 2773637.72,
"ownedAfter": 2705637, "plan10b51": true, "filed": "2026-09-23",
"url": "https://www.sec.gov/Archives/edgar/data/1045810/000169684126000014/wk-form4_1790196985.xml"},
...
]
}
On a cold cache, that call made 7 requests to SEC: the ticker map, the company's submissions index and five Form 4 XML files. The response header x-sec-requests: 7 reports the count.
2. Apple net income from XBRL
curl -s $URL -H 'content-type: application/json' -H 'accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"get_company_concept","arguments":{"ticker_or_cik":"AAPL","concept":"NetIncomeLoss","period":"annual","limit":4}}}'
{
"company": {"name": "Apple Inc.", "cik": "0000320193"},
"concept": "us-gaap:NetIncomeLoss",
"label": "Net Income (Loss) Attributable to Parent",
"unit": "USD", "period": "annual", "totalPeriods": 19,
"values": [
{"value": 112010000000, "start": "2024-09-29", "end": "2025-09-27", "fy": 2025, "form": "10-K", "filed": "2025-10-31"},
{"value": 93736000000, "start": "2023-10-01", "end": "2024-09-28", "fy": 2025, "form": "10-K", "filed": "2025-10-31"},
{"value": 96995000000, "start": "2022-09-25", "end": "2023-09-30", "fy": 2025, "form": "10-K", "filed": "2025-10-31"},
...
]
}
Look at fy. It's SEC's fiscal year of the filing that reported the value, not of the period, so the FY2024 figure shows fy: 2025. Use start/end to know which period a value belongs to.
3. Cluster buys across the market
curl -s $URL -H 'content-type: application/json' -H 'accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"get_market_insider_buys","arguments":{"days":7,"min_insiders":2,"limit":3}}}'
{
"window": {"days": 7, "from": "2026-10-17", "to": "2026-10-24"},
"dataUpdatedAt": "2026-10-24T04:40:38.877Z",
"issuers": 3, "clusterBuys": 3,
"results": [
{"ticker": "RAPP", "issuer": "Rapport Therapeutics, Inc.", "insiderCount": 6, "clusterBuy": true,
"totalValueUsd": 1664824.35, "totalShares": 61694, "avgPrice": 26.9852,
"firstDate": "2026-10-21", "lastDate": "2026-10-23",
"insiders": [{"name": "Ignelzi Troy A.", "role": "Chief Financial Officer", "valueUsd": 143550}, ...]},
{"ticker": "CHCO", "issuer": "CITY HOLDING CO", "insiderCount": 4, "totalValueUsd": 68222.4, ...},
{"ticker": "RENT", "issuer": "Rent the Runway, Inc.", "insiderCount": 3, "totalValueUsd": 6120515.95, ...}
],
"note": "Open-market, non-derivative purchases only. Not investment advice."
}
This call made zero SEC requests because it reads from a pre-built store (more on that below). Dates are UTC, which is why the window ends on the 24th.
How it works
The whole thing is one Cloudflare Worker on the free plan:
-
MCP transport.
/mcpuses the official MCP TypeScript SDK's web-standard Streamable HTTP transport in stateless JSON mode. There are no sessions and no Durable Object per client. Each POST stands alone, and GET/DELETE return 405. Each tool maps to one REST endpoint, and acompact()function trims the REST JSON down to fewer fields and capped rows so it doesn't fill the model's context. The same Worker also serves that REST API (/v1/..., documented inopenapi.yaml). -
SEC etiquette. Every request to SEC carries a declared User-Agent with a contact email. Requests are spaced at least 115 ms apart, and a global Durable Object rate limiter hands out time slots so that all Worker isolates together stay near 8.7 req/s, under SEC's 10 req/s ceiling. On 429/5xx the Worker backs off (honoring
Retry-After) and retries up to three times. A 403 gets one retry and then a clear error. - Caching. Lookups go through three layers: isolate memory, then the Cloudflare Cache API, then KV for selected keys. TTLs follow how often the data changes. The ticker map and resolutions are cached for 24 h, parsed Form 4s for 30 days (filings don't change), submissions for 10 min, XBRL snapshots and concepts for 6 h, and full-text search for 15 min.
-
Market-wide buys. A cron runs every 10 minutes. It queries EDGAR full-text search for new Form 4s, parses up to 40 per run, and keeps open-market purchases (code P, non-derivative) in a KV store.
get_market_insider_buysgroups that store by issuer. -
Ticker resolution. The ticker file is searched with a regex instead of
JSON.parse, which keeps it inside the free plan's CPU budget.
Limits and caveats
-
Shallow per-call history.
get_insider_tradesparses at most 25 recent Form 4 filings per call (default 5). The free plan allows about 50 subrequests per invocation, so this isn't a tool for pulling ten years of history. - Market scan coverage. The cluster-buy data covers at most 30 days and only starts from when the store was first populated. During a burst of filings the cron can fall behind.
-
XBRL is only as clean as the filings. Companies choose different tags (
Revenuesvs.RevenueFromContractWithCustomerExcludingAssessedTax), and some metrics will come back null. Check thetagfield in the snapshot. -
Shared free endpoint. The public instance has no key and no SLA. Under heavy load you'll queue behind the global SEC limit or get a 503 asking you to retry. For anything important, deploy your own copy (the README covers it: a KV namespace, your own
SEC_USER_AGENT, thenwrangler deploy). You can protect/mcpwithMCP_API_KEYS. - Not investment advice, not affiliated with the SEC. The data is public domain and comes straight from EDGAR. Interpreting it is up to you. A 10b5-1 sale means something very different from a discretionary open-market buy.
Links
- Source code (MIT): https://github.com/monriah-studio/sec-edgar-mcp-remote
- For scheduled or bulk Form 4 pulls outside an agent loop, there's an Apify actor: https://apify.com/monriah-studio/sec-form4-insider-trades
Issues and pull requests are welcome on the repo.
Written with AI assistance and checked by a human.
來源:DEV Community · dev.to