Skip to main content
Glama
menlopy

Finance Intelligence MCP Server

by menlopy
README.md
# Finance Intelligence MCP Server

[![Python 3.12+](https://img.shields.io/badge/python-3.12+-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
[![Checked with mypy](http://www.mypy-lang.org/static/mypy_badge.svg)](http://mypy-lang.org/)

A production-grade, asynchronous Model Context Protocol (MCP) server that grants AI assistants (Claude Desktop, Cursor, ChatGPT, VS Code, etc.) access to real-time financial market data, company metrics, and history. 

Powered by **FastMCP**, **yfinance**, and **Pydantic**, this server uses advanced thread-offloading, caching, and robust error isolation to provide standard JSON-RPC tools with zero crashes.

---

## Architecture Overview

```
               +--------------------------------------+
               |    LLM Client (e.g. Claude Desktop)  |
               +------------------+-------------------+
                                  |
                                  | (JSON-RPC over stdio / SSE)
                                  v
               +------------------+-------------------+
               |      Finance Intelligence MCP        |
               |                                      |
               |   +------------------------------+   |
               |   |          server.py           |   |
               |   +--------------+---------------+   |
               |                  |                   |
               |                  v                   |
               |   +------------------------------+   |
               |   |   tools (stocks / companies) |   |
               |   +--------------+---------------+   |
               |                  |                   |
               |                  v                   |
               |   +------------------------------+   |
               |   |        clients/yahoo.py      |   |
               |   |   (Thread Pool & TTL Cache)  |   |
               |   +--------------+---------------+   |
               +------------------|-------------------+
                                  |
                                  v (asyncio.to_thread)
               +------------------+-------------------+
               |         Yahoo Finance Service        |
               +--------------------------------------+
```

### Key Design Decisions

1. **Async Thread Pool Execution**
   `yfinance` is fundamentally a blocking synchronous library. Directly calling it in async tool handlers would block the event loop, freezing the MCP server. We offload every `yfinance` call to a thread pool via `asyncio.to_thread`.
2. **In-Memory TTL Caching**
   To prevent Yahoo Finance rate limits and reduce tool latency during conversational loops, we implement a thread-safe, in-memory cache with a configurable TTL (default: 5 minutes) for ticker info and history query responses.
3. **Safe Log Handling**
   Stdout (`sys.stdout`) is strictly reserved for the MCP JSON-RPC protocol transport. Standard logs are redirected entirely to stderr (`sys.stderr`) using a custom structured logger to prevent channel corruption.
4. **Crash-Resilient Tool Handlers**
   Every tool is wrapped in strict try-except blocks. Instead of crashing the server, exceptions (e.g., TickerNotFound, network timeouts) are caught, logged, and returned as structured JSON error responses.

---

## Features & Available MCP Tools

The server exposes 5 standardized tools:

| Tool Name | Parameters | Description | Returns |
| :--- | :--- | :--- | :--- |
| `search_company` | `query: str` | Search for matching company names, tickers, and exchanges | JSON array of results |
| `get_stock_price` | `symbol: str` | Retrieve real-time pricing and basic exchange details | Current price, state, currency, time |
| `get_stock_info` | `symbol: str` | Retrieve key fundamentals, stats, and company info | Market cap, P/E, beta, dividend yield, etc. |
| `compare_companies` | `symbol1: str`, `symbol2: str` | Side-by-side metric comparison of two tickers | Structured comparative matrix |
| `get_stock_history` | `symbol: str`, `period: str` | Download historical prices (1d, 5d, 1mo, 3mo, 6mo, 1y, 5y, max) | Chronological price records |

---

## Installation

### Prerequisites
- Python 3.12 or newer
- Virtual Environment or `uv` package manager

### Standard Setup

1. **Clone the repository:**
   ```bash
   git clone https://github.com/yourusername/finance-intelligence-mcp.git
   cd finance-intelligence-mcp
   ```

2. **Create a virtual environment and install dependencies:**
   ```bash
   python3 -m venv .venv
   source .venv/bin/activate
   pip install --upgrade pip
   pip install -e ".[dev]"
   ```

3. **Configure the environment:**
   Create a `.env` file from the example:
   ```bash
   cp .env.example .env
   ```
   *(Adjust values like `CACHE_TTL_SECONDS` or `LOG_LEVEL` if needed.)*

---

## Usage

### Running Locally

To run the server in the default **stdio** mode (which local clients like Claude Desktop use):
```bash
python -m src.main
```

To run the server in **SSE (HTTP)** mode:
```bash
python -m src.main --transport sse --port 8000
```

---

## Client Integration Configurations

### 1. Claude Desktop Configuration

Add the following to your Claude Desktop configuration file (typically at `~/Library/Application Support/Claude/claude_desktop_config.json` on macOS or `%APPDATA%\Claude\claude_desktop_config.json` on Windows):

#### Standard Execution (Python Venv):
```json
{
  "mcpServers": {
    "finance-intelligence": {
      "command": "/Users/YOUR_USER/Desktop/finance mcp/.venv/bin/python",
      "args": [
        "-m",
        "src.main"
      ],
      "env": {
        "LOG_LEVEL": "INFO",
        "CACHE_TTL_SECONDS": "300"
      }
    }
  }
}
```

#### Docker Execution:
```json
{
  "mcpServers": {
    "finance-intelligence-docker": {
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "finance-intelligence-mcp:latest"
      ]
    }
  }
}
```

### 2. Cursor Configuration

To add the server to Cursor:
1. Open Cursor Settings -> Features -> **MCP**.
2. Click **+ Add New MCP Server**.
3. Fill out the fields:
   - **Name**: `Finance Intelligence`
   - **Type**: `command`
   - **Command**: `/path/to/project/.venv/bin/python -m src.main`

---

## Docker Containerization

1. **Build the image:**
   ```bash
   docker build -t finance-intelligence-mcp:latest .
   ```

2. **Run the image locally in stdio mode:**
   ```bash
   docker run -i --rm finance-intelligence-mcp:latest
   ```

3. **Run the image locally in HTTP/SSE mode:**
   ```bash
   docker run -d -p 8000:8000 --name finance-mcp finance-intelligence-mcp:latest --transport sse --port 8000
   ```

---

## Example Prompts

Here are some prompt examples you can ask your AI model once the server is connected:

- **Search**: *"Find the stock ticker for Nvidia."* -> Triggers `search_company(query="Nvidia")`
- **Price**: *"What is the current stock price and market state of Apple (AAPL)?"* -> Triggers `get_stock_price(symbol="AAPL")`
- **Info**: *"Show me the key financials for Microsoft, including market cap, beta, and P/E ratio."* -> Triggers `get_stock_info(symbol="MSFT")`
- **Comparison**: *"Compare Apple and Microsoft stocks side by side."* -> Triggers `compare_companies(symbol1="AAPL", symbol2="MSFT")`
- **History**: *"Analyze the historical performance of Tesla (TSLA) over the past month."* -> Triggers `get_stock_history(symbol="TSLA", period="1mo")`

---

## Quality & Testing

We enforce code quality through automated checks.

### Run Tests
```bash
pytest tests/ -v
```

### Run Linter
```bash
ruff check src/ tests/
```

### Run Type Checker
```bash
mypy src/
```

---

## Roadmap

## Roadmap

- [x] Stock prices
- [x] Company information
- [x] Stock comparison
- [ ] Financial statements
- [ ] Crypto support
- [ ] Macroeconomic indicators
- [ ] Portfolio analysis
- [ ] DCF valuation

---

## Contributing

Contributions are welcome! Please open an issue or submit a pull request with any suggestions or improvements. Make sure to run the formatting and test suite before submitting code.

---

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.