Metadata-Version: 2.4
Name: fundamentals-mcp
Version: 0.1.0
Summary: Unofficial MCP server for read-only fundamental, macro & news data (SEC EDGAR + FRED + Tavily)
Project-URL: Homepage, https://github.com/SimonTarara62/fundamentals-mcp
Project-URL: Repository, https://github.com/SimonTarara62/fundamentals-mcp
Project-URL: Issues, https://github.com/SimonTarara62/fundamentals-mcp/issues
Project-URL: Changelog, https://github.com/SimonTarara62/fundamentals-mcp/blob/main/CHANGELOG.md
Author: Simon Tarara
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: edgar,fastmcp,finance,fred,fundamentals,macro,mcp,mcp-server,model-context-protocol,tavily
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Office/Business :: Financial
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Requires-Dist: anyio>=4
Requires-Dist: fastmcp<4,>=3
Requires-Dist: httpx>=0.27
Requires-Dist: pydantic>=2
Provides-Extra: dev
Requires-Dist: mypy; extra == 'dev'
Requires-Dist: pytest; extra == 'dev'
Requires-Dist: pytest-asyncio; extra == 'dev'
Requires-Dist: respx; extra == 'dev'
Requires-Dist: ruff; extra == 'dev'
Description-Content-Type: text/markdown

<!-- mcp-name: io.github.SimonTarara62/fundamentals-mcp -->

# Fundamentals MCP

Self-hosted **Model Context Protocol (MCP)** server for **read-only fundamental,
macro & news data**, written in Python on
[FastMCP](https://github.com/jlowin/fastmcp). Bring-your-own keys, no broker
credentials, no execution — the read-only data layer of an LLM trading "desk"
that composes with the (also unofficial)
[Capital.com MCP Server](https://github.com/SimonTarara62/capitalcom-mcp-server)
for execution.

**Works with** Claude Desktop · Claude Code · Cursor · VS Code (Copilot) ·
Windsurf — any MCP client.

> ⚠️ **Unofficial & educational.** Not affiliated with SEC EDGAR, FRED, Tavily,
> or any broker. Read-only data for informational purposes only; **not financial
> advice**. Data may be delayed or revised — verify against the cited primary
> source before relying on it. No trading credentials, no order execution.
> Apache-2.0 licensed.

## Install

Not on PyPI yet — install from this repo. Two paths:

### A. Run from a clone (recommended for local testing)

Requires [`uv`](https://docs.astral.sh/uv/) (`curl -LsSf https://astral.sh/uv/install.sh | sh`):

```bash
git clone https://github.com/SimonTarara62/fundamentals-mcp ~/dev/fundamentals-mcp
cd ~/dev/fundamentals-mcp
uv sync                                # creates .venv with all deps
uv run fundamentals-mcp                # smoke test — starts stdio server
```

You can iterate on the source and pull updates without reinstalling.

### B. Run via `uvx` without a clone

```bash
uvx --from git+https://github.com/SimonTarara62/fundamentals-mcp \
  fundamentals-mcp
```

`uvx` fetches the package into a throwaway environment on each launch (cached).

### C. `pip` fallback (no uv)

```bash
git clone https://github.com/SimonTarara62/fundamentals-mcp ~/dev/fundamentals-mcp
cd ~/dev/fundamentals-mcp
python3 -m venv .venv && . .venv/bin/activate
pip install -e .
fundamentals-mcp                       # smoke test
```

## 1. Add your keys (once)

The server is **credential-free at startup** — every tool returns a typed
`not_configured` result when its key is missing, no crash. Add keys only for the
tools you want to use.

```bash
cp .env.example .env                   # gitignored; fill in below
```

Edit `.env` with whatever subset you need:

| key | required for | how to get one |
|---|---|---|
| `FUND_EDGAR_USER_AGENT` | `resolve_instrument`, `get_fundamentals` | Any descriptive string with your name + email per [SEC EDGAR fair-use rules](https://www.sec.gov/os/accessing-edgar-data) (e.g. `fundamentals-mcp (you@example.com)`). No signup — public-domain data. |
| `FUND_FRED_API_KEY` | `get_macro` | Free key from [fred.stlouisfed.org/docs/api/api_key.html](https://fred.stlouisfed.org/docs/api/api_key.html). |
| `FUND_TAVILY_API_KEY` | `get_news` | Free tier at [app.tavily.com](https://app.tavily.com/). |

The server's request rate is gated by `FUND_EDGAR_MIN_INTERVAL` (default 0.2 s),
`FUND_FRED_MIN_INTERVAL` (default 0.6 s), and `FUND_TAVILY_MIN_INTERVAL`
(default 1.0 s) — all comfortably under each provider's published cap.

## 2. Add the server to your client

All clients use the same `command` / `args` / `env` shape. Pick the snippet for
the clone path you used:

### Claude Desktop

`~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) /
`%APPDATA%\Claude\claude_desktop_config.json` (Windows).

**A. From a clone** (replace `/Users/you/dev/fundamentals-mcp` with your path):

```json
{
  "mcpServers": {
    "fundamentals": {
      "command": "uv",
      "args": ["--directory", "/Users/you/dev/fundamentals-mcp", "run", "fundamentals-mcp"],
      "env": {
        "FUND_EDGAR_USER_AGENT": "fundamentals-mcp (you@example.com)",
        "FUND_FRED_API_KEY": "your-fred-key",
        "FUND_TAVILY_API_KEY": "your-tavily-key"
      }
    }
  }
}
```

**B. From `uvx` (no clone)**:

```json
{
  "mcpServers": {
    "fundamentals": {
      "command": "uvx",
      "args": ["--from", "git+https://github.com/SimonTarara62/fundamentals-mcp", "fundamentals-mcp"],
      "env": {
        "FUND_EDGAR_USER_AGENT": "fundamentals-mcp (you@example.com)",
        "FUND_FRED_API_KEY": "your-fred-key",
        "FUND_TAVILY_API_KEY": "your-tavily-key"
      }
    }
  }
}
```

Restart Claude Desktop. In a new chat you should see `fundamentals` in the MCP
indicator; try `Call ping` to confirm.

### Claude Code

```bash
# From a clone:
claude mcp add --transport stdio \
  --env FUND_EDGAR_USER_AGENT="fundamentals-mcp (you@example.com)" \
  --env FUND_FRED_API_KEY="your-fred-key" \
  --env FUND_TAVILY_API_KEY="your-tavily-key" \
  fundamentals -- uv --directory /Users/you/dev/fundamentals-mcp run fundamentals-mcp

# From uvx:
claude mcp add --transport stdio \
  --env FUND_EDGAR_USER_AGENT="fundamentals-mcp (you@example.com)" \
  --env FUND_FRED_API_KEY="your-fred-key" \
  --env FUND_TAVILY_API_KEY="your-tavily-key" \
  fundamentals -- uvx --from git+https://github.com/SimonTarara62/fundamentals-mcp fundamentals-mcp
```

### Cursor

`~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (project) — same shape as
Claude Desktop above.

### VS Code (Copilot)

`.vscode/mcp.json` — note the root key is `servers` and `type: "stdio"`:

```json
{
  "servers": {
    "fundamentals": {
      "type": "stdio",
      "command": "uv",
      "args": ["--directory", "/Users/you/dev/fundamentals-mcp", "run", "fundamentals-mcp"],
      "env": {
        "FUND_EDGAR_USER_AGENT": "fundamentals-mcp (you@example.com)",
        "FUND_FRED_API_KEY": "your-fred-key",
        "FUND_TAVILY_API_KEY": "your-tavily-key"
      }
    }
  }
}
```

### Windsurf

`~/.codeium/windsurf/mcp_config.json` — same shape as Claude Desktop above.

## Tools

- `ping` — liveness check; returns server name + UTC timestamp.
- `get_macro(series)` — latest value of a FRED economic series (e.g.
  `CPIAUCSL`, `FEDFUNDS`, `DGS10`, `SP500`, `VIXCLS`), as a provenance-stamped
  envelope. Requires `FUND_FRED_API_KEY`; returns a typed `not_configured`
  result otherwise.
- `resolve_instrument(query)` — resolve a US-equity ticker or company name to
  its SEC CIK with confidence + alternatives. Requires `FUND_EDGAR_USER_AGENT`.
- `get_fundamentals(ticker, metrics?)` — latest annual (10-K) company
  fundamentals from SEC EDGAR. Surfaces **31 canonical metrics** across income
  statement (revenue, gross profit, R&D, SG&A, operating income, tax, net
  income, EPS basic & diluted), balance sheet (working-capital components,
  PP&E, total assets/liabilities, equity, retained earnings), cash flow
  (CFO/CFI/CFF, CapEx, SBC, dividends paid), and share counts (outstanding +
  weighted-average basic & diluted). Each value is provenance-stamped (`USD` or
  `shares`/`USD/share`). US equities only; requires `FUND_EDGAR_USER_AGENT`.
  Concept coverage is cross-checked across industries (banks, insurers,
  utilities, retailers, semis, …); `total_liabilities` is derived
  (Assets − equity, `computed` provenance) when a filer doesn't tag it, and
  stale datapoints are flagged via `freshness.staleness`. Run
  `scripts/edgar_coverage.py` (needs `FUND_EDGAR_USER_AGENT`) to re-check
  coverage live across 17 tickers (the 12 core sectors plus 5 high-traffic
  names). Last sweep: 2026-06-17. EDGAR requests are rate-limited via
  `FUND_EDGAR_MIN_INTERVAL` (default 0.2 s ≈ 5 req/s, under the 10 req/s cap).
- `get_news(query, lookback_days?, max_results?)` — citation-bound news
  snippets for any free-text query (ticker, company, instrument, topic). Works
  for all 5 asset classes. Returns an envelope with `facts=[]` (always) and
  `context=[NewsItem...]`. **Search never populates a numeric value** —
  enforced structurally (`NewsItem` has no `value` field). Requires
  `FUND_TAVILY_API_KEY`; without it returns a typed empty-context envelope with
  a warning. Rate-limited via `FUND_TAVILY_MIN_INTERVAL` (default 1.0 s).

## Design intent

- **Single bounded context:** read-only fundamental/macro/news data only. No
  trading credentials, no execution. Credential isolation keeps a data-parsing
  bug physically unable to touch order execution.
- **Bring-your-own key (BYO):** you supply your own data-provider keys, so this
  server redistributes no licensed data. The user is the data licensee.
- **Provenance-first:** every value carries its source, units, and as-of date
  so an LLM can attribute rather than hallucinate. Numbers come only from
  structured sources; search supplies narrative/context, never numbers.
- **Thin server:** the server exposes data; analysis/scoring lives in the
  skill/orchestration layer, not here.
- **Credential-free startup:** starts and answers tool introspection with no
  keys; upstream clients are built lazily on first call.

## Contributing

Direction is proposed through **GitHub issues** (look for `good first issue`,
`provider-request`, `metric-request`, `instrument-mapping`). See
[CONTRIBUTING.md](CONTRIBUTING.md) for the legal-clean checklist and how to add
a provider, a metric, or an instrument mapping.

## License

[Apache-2.0](LICENSE).
