{
  "markdown": "# soi-mcp\n\n<!-- mcp-name: io.github.mcpwright/soi-mcp -->\n\n**IRS income & tax statistics by ZIP code, inside your agent.** An [MCP](https://modelcontextprotocol.io)\nserver that lets an LLM pull the income distribution, tax, credits, and deductions of any U.S. ZIP\nstraight from the IRS Statistics of Income (SOI) — built on Anthropic's official\n[`mcp` Python SDK](https://github.com/modelcontextprotocol/python-sdk).\n\nAll tools are **read-only** and the data is **public domain** (a U.S. government work) — **no API\nkey required**. The dataset is downloaded once into a local SQLite store and served offline.\n\n> Status: **published** — `uvx mcpwright-soi` (PyPI) and listed in the official MCP Registry as\n> `io.github.mcpwright/soi-mcp`. 10 tools, working today (see below). The IRS SOI ZIP release lags ~2–3 years; the\n> latest available year (currently **Tax Year 2022**) loads by default, and older years are one\n> `refresh <year>` away. See the roadmap for what's next.\n\n## Tools\n\n| Tool | What it does |\n|---|---|\n| `lookup_zip(zip_code)` | Confirm a ZIP has SOI data → state, number of returns, number of individuals, tax year. A good first call. |\n| `get_income(zip_code)` | Adjusted gross income (AGI), average AGI per return, and income components: salaries/wages, taxable interest, ordinary dividends, business net income, net capital gain. |\n| `get_agi_distribution(zip_code)` | **The distinctive one.** The ZIP's returns and AGI split across the six IRS AGI brackets (<$25k, $25–50k, $50–75k, $75–100k, $100–200k, $200k+), with each bracket's share — the income *shape* of a ZIP, not just an average. |\n| `get_tax(zip_code)` | Income tax, income tax before credits, total tax liability (broader — includes self-employment tax, etc.), total tax payments, and average total tax per return. |\n| `get_credits(zip_code)` | EITC take-up (overall and split by number of qualifying children: none / one / two / three or more) and the additional (refundable) child tax credit. |\n| `get_deductions(zip_code)` | Standard vs. itemized deductions (count and amount), the taxes-paid (SALT) deduction, and the percent of returns that itemized. |\n| `get_filing_status(zip_code)` | Single / married-filing-jointly / head-of-household return counts, elderly returns (age 65+), and the count and share of electronically filed returns. |\n| `compare_zips(zips, metric)` | Rank several ZIPs by one metric (e.g. `avg_agi_per_return`, `pct_returns_200k_plus`, `total_tax_liability`, `eitc_amount`), highest first. |\n| `get_state_totals(state)` | A whole state's totals and AGI-bracket mix (returns, individuals, AGI, average AGI per return, income tax, total tax liability), from the IRS state rollup. Accepts `\"CA\"` or `\"California\"`. |\n| `get_soi_field(zip_code, field)` | Escape hatch: the raw value of one SOI field code (e.g. `A00100` for AGI, `N1` for returns) for a ZIP, summed across brackets, with its label and unit. Limited to the fields in the store. |\n\nAll dollar amounts are returned in **whole USD** (the source reports thousands). Counts are\nnumbers of returns, rounded by the IRS to the nearest 10.\n\n## Install\n\nRequires Python 3.12+. The zero-clone way to run it (the PyPI package is `mcpwright-soi`; the\ncommand, server, and tools are all \"soi\"):\n\n```bash\nuvx mcpwright-soi\n```\n\nThe first tool call downloads the latest SOI ZIP file (~200 MB) into a local SQLite store under\nyour OS cache directory and serves everything offline thereafter. To pre-load (or to pick a\nspecific tax year) without waiting for the first query:\n\n```bash\nuvx mcpwright-soi setup            # download the latest available year\nuvx mcpwright-soi refresh 2021     # re-pull a specific older year for comparison\n```\n\n### Claude Code\n\n```bash\nclaude mcp add soi -- uvx mcpwright-soi\n```\n\n### Claude Desktop\n\nAdd to `claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"soi\": { \"command\": \"uvx\", \"args\": [\"mcpwright-soi\"] }\n  }\n}\n```\n\n### OpenAI Agents SDK (Python)\n\nIt's a standard MCP server, so it works with any MCP-capable client — not just Claude.\nWith the [OpenAI Agents SDK](https://openai.github.io/openai-agents-python/mcp/):\n\n```python\nfrom agents import Agent, Runner\nfrom agents.mcp import MCPServerStdio\n\nasync def main():\n    async with MCPServerStdio(\n        name=\"soi\",\n        params={\"command\": \"uvx\", \"args\": [\"mcpwright-soi\"]},\n    ) as soi:\n        agent = Agent(\n            name=\"Analyst\",\n            instructions=\"Use the SOI tools for IRS income and tax data by ZIP.\",\n            mcp_servers=[soi],\n        )\n        result = await Runner.run(\n            agent, \"What's the income distribution of ZIP 90210 vs 10001?\"\n        )\n        print(result.final_output)\n```\n\n### Any other MCP client (Cursor, VS Code, Cline, Goose, Zed, …)\n\nThey all launch a stdio MCP server the same way — point yours at:\n\n```json\n{\n  \"mcpServers\": {\n    \"soi\": { \"command\": \"uvx\", \"args\": [\"mcpwright-soi\"] }\n  }\n}\n```\n\n> Hosted chat connectors (e.g. ChatGPT connectors) expect a **remote** MCP server over\n> Streamable HTTP; `mcpwright-soi` runs locally over stdio.\n\n> **Storage:** the dataset lives in a SQLite file under your OS cache dir (override with the\n> `SOI_MCP_STORE` env var). Delete it any time; `setup` / `refresh` rebuilds it.\n\n> **A note on suppression:** the IRS excludes ZIPs with fewer than 100 returns (folding them into\n> a \"99999\" bucket) and suppresses line items with fewer than 20 returns. Summed ZIP totals can\n> therefore slightly understate reality and won't exactly equal the state total. All figures are\n> aggregates of filed returns, not a population census.\n\n## Develop\n\n```bash\ngit clone https://github.com/mcpwright/soi-mcp && cd soi-mcp\nuv sync\nuv run pytest                                          # tests (mocked download + seeded SQLite)\nuv run ruff check src/ && uv run ruff format --check src/   # lint + format\nuv run mypy                                            # strict type checking\nuv run mcp dev src/soi_mcp/server.py                   # poke the tools in the MCP Inspector\n```\n\n## Roadmap\n\n- [x] `lookup_zip` / `get_income` / `get_agi_distribution` — the income backbone\n- [x] `get_tax` / `get_credits` / `get_deductions` / `get_filing_status` — the tax side\n- [x] `compare_zips` — rank ZIPs by a metric\n- [x] `get_state_totals` — state rollups from the IRS 00000 row\n- [x] `get_soi_field` — raw-field escape hatch\n- [x] `setup` / `refresh [year]` — download once, re-pull or pick an older tax year\n- [x] Publish to PyPI (`mcpwright-soi`) + the official MCP Registry (`io.github.mcpwright/soi-mcp`)\n- [ ] Multi-year queries in one call (trend a ZIP across tax years)\n\n## Privacy\n\nsoi-mcp runs entirely **on your machine**. It collects, stores, or transmits **no personal data**\n— no accounts, no tracking, no telemetry. Its only outbound requests go to the **U.S. IRS** static\nfile host (`www.irs.gov/pub/irs-soi`) to download the public SOI ZIP-code CSV; no API key is\nneeded and nothing about your queries leaves your machine. The downloaded dataset is cached **on\ndisk** as a local SQLite file (under your OS cache dir, or `SOI_MCP_STORE`); delete it any time.\n\nFull policy: **https://mcpwright.com/privacy/**\n\n## Questions & feedback\n\n- **Questions, ideas, or \"could it do X?\"** → [**Discussions**](https://github.com/mcpwright/soi-mcp/discussions)\n- **Bugs & concrete feature requests** → [**Issues**](https://github.com/mcpwright/soi-mcp/issues)\n\nContributions welcome — and if you build something with it, I'd love to hear about it.\n\n---\n\nPart of [**mcpwright**](https://github.com/mcpwright) · built by [Devender Gollapally](https://github.com/devender)\n",
  "bytes": 7612,
  "sha": "86562b03c1512b415ed57257b72f8b583517db2b973bac02a4640a9ae0019eb8",
  "repo_slug": "mcpwright/soi-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_mcpwright_soi_mcp_0b420084/readme"
}