Metadata-Version: 2.4
Name: fundamentals-mcp
Version: 0.1.1
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.

## Quickstart — Claude Desktop in 30 seconds (no signup)

1. Click **Download `fundamentals-mcp.mcpb`** on the
   [latest Release](https://github.com/SimonTarara62/fundamentals-mcp/releases/latest)
   page (under the Assets list).
2. Double-click the downloaded file. Claude Desktop opens an Install dialog.
3. In the **EDGAR User-Agent** field, type
   `fundamentals-mcp (your-name your@email)`. Use your real email — SEC fair-use
   rules ask filers to identify themselves so they can be contacted if their
   requests cause problems. No signup; this is just a string you invent.
4. **Leave FRED and Tavily blank.** You can add them later — see
   [How to get the keys](#how-to-get-the-keys-when-you-want-them).
5. Click **Install**. Quit and reopen Claude Desktop.
6. In a new chat:
   - *Call the `ping` tool* → server name + UTC timestamp.
   - *Resolve NVDA and get its fundamentals* → 31 metrics with provenance.

You now have a working MCP server with no terminal, no JSON editing, and no
external signups. To enable macro data (FRED) or news search (Tavily), add
those keys later through the same Claude Desktop Extensions UI — see
[Adding keys after install](#adding-keys-after-install).

## What works with each key

| Set up | Tools that work | Try asking |
|---|---|---|
| **EDGAR User-Agent only** (default) | `ping`, `resolve_instrument`, `get_fundamentals` | "Resolve NVDA", "Get AAPL fundamentals", "What's MSFT's revenue?" |
| **+ FRED API key** | + `get_macro` | "Latest SP500", "10-year Treasury yield", "CPI for last month" |
| **+ Tavily API key** | + `get_news` | "Recent news on NVDA earnings", "Headlines about Fed rate decision" |

Three of the five tools work with the EDGAR User-Agent alone — no external
signups. FRED and Tavily are add-ons for macro and news data.

## How to get the keys (when you want them)

| Key | Service | How long | How to get it |
|---|---|---|---|
| **EDGAR User-Agent** | SEC (no signup) | < 30 s | Self-invented string per [SEC fair-use rules](https://www.sec.gov/os/accessing-edgar-data). Format: `your-name your@email`. Use a real address so SEC can contact you. Avoid parenthetical URLs (some EDGAR endpoints reject them). |
| **FRED API key** | [St. Louis Fed](https://fred.stlouisfed.org/docs/api/api_key.html) | ~ 2 min | Click "Request API Key", verify email, copy the key from the dashboard. Free; no rate limits below ~120 req/min (this server defaults to ~100 req/min). |
| **Tavily API key** | [Tavily](https://app.tavily.com/) | ~ 1 min | Sign in with GitHub or Google, copy the API key from the dashboard. Free tier covers casual research; paid tiers for heavier use. |

## Adding keys after install

**If you installed via .mcpb (MCPB bundle)** — UI path, no terminal:

1. Open Claude Desktop → **Settings → Extensions** (or wherever your version
   surfaces installed MCP extensions — the exact menu name may differ between
   Claude Desktop releases).
2. Find **Fundamentals MCP**, click the ⚙ / "Configure" / "Settings" affordance
   on its row.
3. Paste your FRED and/or Tavily key into the corresponding labelled field.
4. Click **Save**. The server picks up the new keys on its next request — no
   full Claude Desktop restart needed.

**If you installed via `uvx`, Homebrew, or source** — terminal path:

- Easiest: re-run the wizard. It prompts for all 3 keys; existing values are
  preserved if you press Enter at a prompt.
  ```bash
  uvx fundamentals-mcp init
  ```
- Or edit `~/.config/fundamentals-mcp/.env` directly. Each line is
  `FUND_KEY=value`. Add or update the line you need. Keep the file mode at
  `0600`:
  ```bash
  chmod 0600 ~/.config/fundamentals-mcp/.env
  ```
- Verify the new state without echoing the key:
  ```bash
  FUND_ENV_FILE=~/.config/fundamentals-mcp/.env uvx fundamentals-mcp doctor
  ```
  Expected: the previously-`(unset)` key now shows as `xx***` (first 2 chars
  + `***`).

## Install

Four options, ordered easiest to most-flexible.

### Option 1 — MCPB bundle (Claude Desktop, double-click)

Best for: anyone who uses Claude Desktop, especially first-time users. **No
terminal, no JSON, no PATH issues.**

Follow the [Quickstart](#quickstart--claude-desktop-in-30-seconds-no-signup)
above. The bundle uses the spec's `uv` server type, so dependencies are
resolved on first run across darwin / linux / win32 — no native-dep bundling.

### Option 2 — `uvx` (terminal, any MCP client)

Best for: terminal-comfortable users on any client (Claude Desktop, Claude
Code, Cursor, VS Code Copilot, Windsurf). Pinnable versions.

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

```bash
uvx fundamentals-mcp init        # interactive: writes 0600 .env + prints client snippet
uvx fundamentals-mcp doctor      # verify config (no secrets printed)
```

The `init` wizard prompts for your three keys, writes a `0600`
`~/.config/fundamentals-mcp/.env`, and prints the ready-to-paste MCP client
config — with the **absolute path to `uvx`** filled in so GUI launchers like
Claude Desktop find it without inheriting your shell PATH.

### Option 3 — Homebrew (macOS / Linux)

Best for: Mac / Linux users who prefer `brew install` over `uv`.

```bash
brew tap simontarara62/tap
brew install fundamentals-mcp
fundamentals-mcp init            # same wizard as Option 2
```

### Option 4 — From source (contributor path)

Best for: contributors / developers who want to hack on the server.

```bash
git clone https://github.com/SimonTarara62/fundamentals-mcp ~/dev/fundamentals-mcp
cd ~/dev/fundamentals-mcp
uv sync
uv run fundamentals-mcp
```

## Configure your MCP client

> If you installed via .mcpb (Option 1 above), this section is **already done
> for you** — Claude Desktop registered the MCP entry when you double-clicked
> the bundle. Skip to [Verify the install](#verify-the-install).

Run `fundamentals-mcp init` (or `uvx fundamentals-mcp init`). The wizard:

1. Asks for your three FUND_* keys (any can be left blank — that tool returns a
   typed `not_configured` result instead of crashing).
2. Writes `~/.config/fundamentals-mcp/.env` at mode `0600`.
3. Prints the exact JSON snippet to paste into your client's config — with the
   absolute path to `uvx` filled in so GUI launchers (Claude Desktop) find it
   without inheriting your shell PATH.

Config file locations:

- **Claude Desktop**: `~/Library/Application Support/Claude/claude_desktop_config.json`
  (macOS) / `%APPDATA%\Claude\claude_desktop_config.json` (Windows)
- **Claude Code**: `claude mcp add fundamentals -- $(which uvx) fundamentals-mcp`
- **Cursor**: `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (project)
- **VS Code (Copilot)**: `.vscode/mcp.json` (root key is `servers`, `type: "stdio"`)
- **Windsurf**: `~/.codeium/windsurf/mcp_config.json`

## Verify the install

The wizard's secret prompts (`FUND_FRED_API_KEY`, `FUND_TAVILY_API_KEY`) are
silent by design — no echo, no confirmation — so you can't tell from the wizard
alone whether a paste succeeded. Use `doctor` to confirm:

```bash
FUND_ENV_FILE=~/.config/fundamentals-mcp/.env uvx fundamentals-mcp doctor
```

Expected output:

```
Configuration loaded
  FUND_FRED_API_KEY      = ab***            # first 2 chars + ***
  FUND_EDGAR_USER_AGENT  = configured
  FUND_TAVILY_API_KEY    = tv***
  FUND_FRED_MIN_INTERVAL = 0.6
  FUND_EDGAR_MIN_INTERVAL= 0.2
  FUND_TAVILY_MIN_INTERVAL = 1.0
```

Each key is redacted to its first 2 characters; the full value never appears.
If you see `(unset)` for FRED or Tavily, the paste didn't take — re-run
`uvx --no-cache fundamentals-mcp init` and try again.

In Claude Desktop, after restart, look for the MCP indicator near the input
box. `fundamentals` should appear as Connected. In a new chat, ask:

> Call the `ping` tool

Expected: the model invokes `ping` and reports `Fundamentals MCP (unofficial)`
plus a UTC timestamp. If FRED/Tavily keys are set, also try:

> Get the latest SP500 value via get_macro
>
> Resolve NVDA and fetch its fundamentals

Both should return structured envelopes with `provenance` and `freshness`
fields. Numbers come from structured sources only; news snippets come
quoted with citation ids — the server never lets search fabricate a number.

## Troubleshooting

**`uvx: command not found`**
You don't have `uv` installed or it's not on PATH. Install with
`curl -LsSf https://astral.sh/uv/install.sh | sh`, then open a fresh
Terminal window (PATH is set in shell rc).

**Wizard prints `"command": "uvx"` (bare) instead of an absolute path**
Means `uvx` wasn't on the shell's PATH that `init` saw. The wizard prints
a warning above the snippet. Fix: re-run `init` from a Terminal where
`which uvx` returns an absolute path.

**`fundamentals` doesn't appear in Claude Desktop after restart**
Claude Desktop launches from the Dock without inheriting your shell PATH,
so `"command": "uvx"` won't resolve. Use the absolute path the wizard
printed (e.g. `/Users/you/.local/bin/uvx`). Tail
`~/Library/Logs/Claude/mcp.log` for the exact error if it still fails.

**Tools return `not_configured` for FRED / Tavily**
Means the key wasn't read. Run `doctor` (see above); if the key shows
`(unset)`, re-run `init` and re-enter. If `doctor` shows `ab***` but the
tool still says `not_configured`, the env file path in your client
config is wrong — make sure `FUND_ENV_FILE` in the JSON snippet matches
the path the wizard printed.

**EDGAR returns 403**
SEC's fair-use rules require a User-Agent that identifies the requester.
Use something like `fundamentals-mcp (you@example.com)` —
*your* email so SEC can contact you if your requests cause problems.
Avoid parenthetical URLs in the User-Agent; some EDGAR endpoints reject them.

**Permissions / `Permission denied: ~/.config/fundamentals-mcp/.env`**
The wizard writes at `0600`. If you're running as a different user than
the wizard ran as, your client can't read the file. Re-run `init` as
the same user that launches Claude Desktop.

## 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).
