MCP server
Query congressional trades from Claude Desktop, Claude Code, or any MCP client — the public API as LLM-callable tools.
@sitekit/woch-mcp is a stdio Model Context Protocol
server that exposes the public data API as read-only tools: trades, politician
profiles, per-ticker activity, and source filings. It works without an API
key at anonymous evaluation limits; set one for production limits.
Install / run
From the monorepo:
pnpm install
pnpm --filter @sitekit/woch-mcp build
pnpm --filter @sitekit/woch-mcp start # stdio server on stdin/stdoutThe built entry point lands at apps/mcp/dist/index.js (the package declares
a woch-mcp bin for when it ships to npm; until then run the local build).
Environment
| Variable | Required | Default | Purpose |
|---|---|---|---|
WOCH_API_URL | no | https://www.wolfofcapitolhill.com | The WoCH deployment to call. |
WOCH_API_KEY | no | — | API key (wch_...) from Account → API keys, sent as Authorization: Bearer. Omit to evaluate anonymously at low limits. |
Client configuration
Claude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"wolves-of-capitol-hill": {
"command": "node",
"args": ["/path/to/wolves-of-capitol-hill/apps/mcp/dist/index.js"],
"env": {
"WOCH_API_KEY": "wch_..."
}
}
}
}Claude Code:
claude mcp add wolves-of-capitol-hill \
--env WOCH_API_KEY=wch_... \
-- node /path/to/wolves-of-capitol-hill/apps/mcp/dist/index.jsDrop the WOCH_API_KEY line entirely to evaluate anonymously.
Tools
| Tool | What it does |
|---|---|
list_trades | Published trades, newest first, keyset-paginated. Filters AND-stack: ticker, politician_slug, chamber, since (ISO 8601), limit (≤100), cursor. |
get_politician | One politician's profile + recent trades + counts, by slug. |
get_ticker | Congressional activity in one symbol: recent trades + aggregates (buys/sells/lastActivity). |
list_filings | Published disclosure filings with official source URLs (chamber, limit, cursor). |
find_politician | Free-text name → ranked slug matches. The API has no name-search endpoint, so this scans up to max_pages × 100 recent trades (default 3, max 8) and fuzzy-matches the distinct politicians found — members with no recent published trades may not appear. |
get_conflicted_trades | Trades with conflictSignal=true, filtered client-side over up to max_pages × 100 feed rows (default 3, hard cap 5); returns nextCursor to continue scanning. |
Semantics the tools spell out for the model
- Amounts are STOCK Act ranges.
amountBucket/amountRangeare the statutory disclosure ranges (e.g.$1,001 – $15,000) — members never disclose exact figures;amountRange.maxisnullwhen unbounded above. See the trades data model. conflictSignalflags a trade overlapping an industry the politician oversees via committee assignments (conflictReasonsays why). It is an editorial signal, not an allegation of illegality.- Errors are readable.
401→ checkWOCH_API_KEY;403→ the plan's upgrade hint;429→ retry-after seconds; a malformed cursor → "pass the exactnextCursor". Anonymous callers get arateLimitWarningin results when the minute window runs low.