Skip to main content
Glama
Open-Agent-Tools

Open Stocks MCP

README.md
# Open Stocks MCP

An MCP (Model Context Protocol) server providing access to stock market data and trading capabilities through multiple broker APIs.

## Features

**🚀 Current Status: v0.6.5 - Multi-Broker Support (Robinhood + Schwab)**
- ✅ **MCP tools** across Robinhood + Schwab (see [Tool Reference](docs/MCP_TOOLS_REFERENCE.md) for current breakdown)
- ✅ **Multi-broker architecture** - Support for Robinhood and Charles Schwab
- ✅ **Complete trading functionality** - stocks, options, order management
- ✅ **Live trading validated** - Robinhood stock and options trading tested with real orders
- ✅ **Production-ready** - HTTP transport, Docker support, comprehensive testing
- ✅ **Schwab integration complete** - OAuth authentication, tools ready for testing (see [Tool Reference](docs/MCP_TOOLS_REFERENCE.md))
- 🔧 **Account details fixed** - Real financial data instead of N/A values

## Installation

```bash
pip install open-stocks-mcp
```

For development:
```bash
git clone https://github.com/Open-Agent-Tools/open-stocks-mcp.git
cd open-stocks-mcp
uv sync   # installs all deps including dev group
```

## Quick Start

### 1. Set Up Credentials

Create a `.env` file:

**For Robinhood:**
```bash
ROBINHOOD_USERNAME=your_email@example.com
ROBINHOOD_PASSWORD=your_password
```

**For Schwab (optional):**
```bash
SCHWAB_API_KEY=your_api_key
SCHWAB_APP_SECRET=your_app_secret
SCHWAB_CALLBACK_URL=https://127.0.0.1:8182/
SCHWAB_TOKEN_PATH=~/.tokens/schwab_token.json

# Enable both brokers
ENABLED_BROKERS=robinhood,schwab
```

**Note:** Schwab requires a developer account and API approval (several days). See [Schwab Setup Guide](docs/SCHWAB_SETUP.md) for full setup instructions.

### 2. Start the Server

**HTTP Transport (Recommended)**
```bash
open-stocks-mcp-server --transport http --port 3001
```

**STDIO Transport**
```bash
open-stocks-mcp-server --transport stdio
```

### 3. Test the Server

```bash
# Health check (HTTP transport)
curl http://localhost:3001/health

# Prometheus metrics (no auth required)
curl http://localhost:3001/metrics

# Interactive testing
uv run mcp dev src/open_stocks_mcp/server/app.py
```

The `/metrics` endpoint exposes:
- `open_stocks_mcp_tool_calls_total` (counter by tool)
- `open_stocks_mcp_tool_avg_calls_per_minute` (gauge by tool; average over the rolling window)
- `open_stocks_mcp_tool_latency_ms` (gauge by tool and quantile: `0.50`, `0.95`, `0.99`)

Distributed tracing setup (OpenTelemetry, Jaeger, Tempo):
- [docs/OPENTELEMETRY_TRACING.md](docs/OPENTELEMETRY_TRACING.md)

### MCP Tool Execution Timeout

Each MCP `tools/call` invocation is bounded by a configurable deadline. Tools that exceed the
deadline return a structured JSON error instead of blocking the server indefinitely.

- **YAML key**: `timeout.tool_execution_timeout_seconds` (default: `30`)
- **Environment override**: `OPEN_STOCKS_MCP_TOOL_EXECUTION_TIMEOUT_SECONDS` (e.g., `60`)

When a tool times out its response body is:
```json
{
  "status": "error",
  "error_type": "ToolExecutionTimeout",
  "failure_class": "timeout",
  "tool": "<tool_name>",
  "timeout_seconds": 30,
  "error": "Tool '...' exceeded the 30s execution limit"
}
```
The MCP result has `isError: true`; HTTP `/mcp` returns status 200 (not 500) so the
client can inspect the structured error. Broker-level request timeouts (Robinhood 16 s,
Schwab 30 s) remain in effect independently and count toward this deadline.

### Operational Circuit Breaker Defaults

Broker call protection is enabled by default and reports state in MCP `health_check`,
MCP `rate_limit_status`, HTTP `/health`, and HTTP `/status`.

- `OPEN_STOCKS_MCP_CIRCUIT_BREAKER_ENABLED` (default: `true`)
- `OPEN_STOCKS_MCP_CIRCUIT_BREAKER_FAILURE_THRESHOLD` (default: `5`)
- `OPEN_STOCKS_MCP_CIRCUIT_BREAKER_COOLDOWN_SECONDS` (default: `60`)

State meanings:
- `closed`: requests flow normally.
- `open`: broker calls fail fast until cooldown expires.
- `half_open`: one probe call is allowed; success resets to `closed`, failure returns to `open`.

## Docker Deployment

**Production Docker Setup:**
```bash
cd examples/open-stocks-mcp-docker
docker-compose up -d
```

**Features:**
- Persistent session storage
- Automatic log rotation
- Health monitoring
- Security headers and CORS

**Kubernetes / Orchestrated Deployment:**
See [examples/kubernetes/README.md](examples/kubernetes/README.md) for Kustomize manifests covering HTTP transport, non-root security context, PVC-backed token/log persistence, and health probes.

## MCP Client Integration

### Claude Desktop
Add to your MCP settings (`~/Library/Application Support/Claude/claude_desktop_config.json`):

```json
{
  "mcpServers": {
    "open-stocks": {
      "command": "open-stocks-mcp-server",
      "args": ["--transport", "stdio"]
    }
  }
}
```

### HTTP Transport Integration
```json
{
  "mcpServers": {
    "open-stocks": {
      "command": "python",
      "args": ["-m", "mcp_http_client", "http://localhost:3001/mcp"]
    }
  }
}
```

## Available Tools

Reference docs and runnable examples:
- [API docs and notebook guide](docs/api/README.md), including the generated
  [tool reference](docs/api/tools.md)

### 🏦 Multi-Broker Support

**Robinhood Tools**:
- All existing Robinhood functionality maintained
- No breaking changes to existing API

**Schwab Tools**:
- Account & Portfolio - account numbers, balances, positions, day trades
- Market Data - quotes, price history, instrument search, market hours, movers
- Trading - market/limit buy/sell, order management, transactions
- Options - chains, expirations, positions, buy/sell, spreads, cancellation
- Streaming - real-time account activity, options quotes, and level2 snapshot
- Dividends/Income - dividends, dividends by symbol, interest payments, stock loan payments

All Schwab tools use `schwab_` prefix (e.g., `schwab_get_portfolio`, `schwab_buy_stock_market`).

---

### Robinhood Tools by Category

### Account & Portfolio
- Account information and details
- Portfolio positions and holdings
- Day trading metrics and history
- Stock and options order history

### Market Data
- Real-time stock quotes and fundamentals
- Market movers and top performers
- Sector analysis and market trends
- Historical price data

### Options Trading
- Options chains and market data
- Position aggregation and analysis
- Historical options data
- Options instrument search

### Watchlists & Profiles ✅ Watchlist Management Tested
- **Watchlist management** - All 5 tools working (add/remove symbols tested with AMC)
- User profile and settings
- Investment preferences
- Account features

### Market Research
- Earnings data and analysis
- Stock ratings and news
- Dividend information
- Corporate actions and splits

### Analytics & Monitoring
- Portfolio analytics
- Performance metrics
- Server health monitoring
- Interest and loan payments

### Notifications
- Account notifications
- Margin calls and interest
- Subscription management
- Referral tracking

### Advanced Instruments
- Multi-symbol instrument lookup
- Enhanced search capabilities
- Level II market data (Gold required)
- Direct instrument access

### Trading Capabilities
**Stock Orders (✅ Live Tested):**
- ✅ Market orders - Buy/sell tested with XOM and AMC
- ✅ Limit orders - Buy/sell tested with XOM ($106) and AMC ($3)
- ✅ Stop-loss orders - Sell tested with AMC (25 shares at $2.50)
- Individual and bulk order cancellation
- ❌ **Deprecated**: Trailing stop orders, fractional shares (uncommon use cases)

**Options Orders (✅ Live Tested):**
- ✅ Options limit orders (buy/sell) - **API bugs fixed**
- ✅ Options discovery and contract search
- ✅ Credit and debit spread strategies - **API bugs fixed, ready for testing**
- Live validation: F $9 put sell order placed successfully

**Order Management:**
- Cancel individual or all orders (stock and options)
- View open positions
- Order status tracking

## Authentication

The server handles Robinhood's authentication requirements:
- **App-Push Approval**: Automatic handling of app-based device approval (approve via Robinhood mobile app).
- **SMS/Email MFA Code**: Set `ROBINHOOD_MFA_CODE` before login attempts to complete code-based verification (time-sensitive, typically 5-10 minutes).
- **Session Persistence**: Cached and encrypted authentication to reduce re-verification.

## Development

### Testing
```bash
uv run pytest                           # All tests (works after uv sync)
uv run pytest -m "journey_account"      # Fast account tests (~1.8s)
uv run pytest -m "journey_market_data"  # Market data tests (~3.8s)
uv run pytest -m "not slow and not exception_test"  # Recommended for development
uv run pytest -m rate_limited           # Opt-in live API tests that may hit broker rate limits
RUN_RATE_LIMITED=1 uv run pytest        # Include rate-limited tests in a full run
uv run pytest -m performance tests/performance -v  # Mocked, CI-safe benchmarks
RUN_PERFORMANCE=1 uv run pytest         # Include performance tests in a full run

# See CLAUDE.md for complete journey testing guide
```

### Code Quality
```bash
ruff check . --fix              # Lint and fix
ruff format .                   # Format code
mypy .                          # Type check
```

### YAML Configuration
Open Stocks MCP can load configuration from `open-stocks-mcp.yaml` or `config.yaml` in the current working directory.
You can also set an explicit path with `OPEN_STOCKS_CONFIG=/path/to/config.yaml` or `OPEN_STOCKS_CONFIG_FILE=/path/to/config.yaml` (`OPEN_STOCKS_MCP_CONFIG` remains supported for backward compatibility).

Environment variables always win over YAML values, including:
- `MCP_SERVER_NAME`, `LOG_LEVEL`
- `RATE_LIMIT_CALLS_PER_MINUTE`, `RATE_LIMIT_CALLS_PER_HOUR`, `RATE_LIMIT_BURST_SIZE`
- `CACHE_TTL_MARKET_SECONDS`, `CACHE_TTL_ACCOUNT_SECONDS`, `CACHE_MAX_SIZE`
- `ENABLE_CACHE`
- `OPEN_STOCKS_MCP_BATCH_SIZE`, `OPEN_STOCKS_MCP_QUEUE_MAX_WAIT`

Feature flags support safe defaults plus per-environment overrides:

```yaml
environment: production
feature_flags:
  brokers.robinhood:
    default: true
  brokers.schwab:
    default: false
    environments:
      production: true
```

Unknown feature flags resolve to disabled (`false`).

See `config.yaml.example` for the supported schema.

### Google ADK Evaluation
```bash
# Set environment variables
export GOOGLE_API_KEY="your-google-api-key"
export ROBINHOOD_USERNAME="email@example.com"
export ROBINHOOD_PASSWORD="password"

# Start Docker server
cd examples/open-stocks-mcp-docker && docker-compose up -d

# Run evaluation
MCP_HTTP_URL="http://localhost:3001/mcp" adk eval examples/google_adk_agent tests/evals/0_list_available_tools_test.json --config_file_path tests/evals/test_config.json
```

## Project Scope

**Completed in v0.7.0-dev:**
- ✅ **Multi-broker architecture** - Abstract broker layer supporting multiple brokers
- ✅ **Schwab integration** - tools across account, market data, trading, options, streaming, and dividends/income (see [Tool Reference](docs/MCP_TOOLS_REFERENCE.md))
- ✅ **OAuth authentication** - Schwab OAuth 2.0 flow with automatic token refresh
- ✅ **Graceful degradation** - Server starts even if broker authentication fails
- ✅ **Backward compatibility** - All Robinhood tools unchanged, no breaking changes

**Completed in v0.6.4:**
- ✅ **Enhanced Options Tools** - New `open_option_positions_with_details()` enriches positions with call/put type
- ✅ **Stock trading API fixes** - Market, limit, and stop-loss buy/sell functions now working correctly
- ✅ **Live stock trading validation** - XOM and AMC orders successfully placed (market, limit, stop-loss)
- ✅ **Tool deprecation** - Removed 4 uncommon trading functions (buy_stock_stop_loss, trailing stops, fractional shares)
- ✅ **Options trading API fixes** - `buy_option_limit`, `sell_option_limit`, and spread strategies now working
- ✅ **Live options validation** - F $9 put successfully traded
- ✅ **Options discovery** - `find_options` function working correctly
- ✅ **Options spreads fixed** - Credit and debit spread functions corrected (API signature, data structure, symbol extraction)
- ✅ **Watchlist management complete** - All 5 watchlist tools working with live testing
- ✅ **Watchlist API fixes** - Fixed response format changes and parameter binding issues
- ✅ **All trading functions ready** - Phase 7 complete, ready for Phase 8

**Next Priority (Schwab Testing):**
- ⏳ Schwab journey tests (blocked by API credentials)
- ⏳ Live Schwab trading validation
- ⏳ Multi-broker integration tests
- ⏳ Schwab-specific documentation

**Out of Scope:**
- Crypto trading tools
- Banking/ACH transfers
- Account modifications
- Deposit/withdrawal functionality

## Contributing

- [CONTRIBUTING.md](CONTRIBUTING.md) — development setup, workflow, and code guidelines
- [contributing/README.md](contributing/README.md) — local debugging and editor configuration

## License

Apache License 2.0 - see [LICENSE](LICENSE) file for details.

## Security

**Important Security Notes:**
- **Live trading capabilities** - Real orders are placed with actual money
- Never commit credentials to version control
- Use proper file permissions for `.env` files
- **Trading validation complete** - Both stock and options trading tested
- Always verify trades before execution in production
- **Options trading note**: Selling options (like puts) can result in assignment and stock ownership

For security concerns, please see our [security policy](SECURITY.md).

---

**Disclaimer:** This software is for educational and development purposes. Trading stocks and options involves substantial risk. Always verify trades and understand the risks before executing any financial transactions.

TDQS

C2.3/5.0

Scored across 150 tools

Disambiguation1/5

Many tools are near-duplicates or have heavily overlapping purposes, such as open_option_positions, open_option_positions_with_details, all_option_positions, and aggregate_option_positions. The same problem appears across account profile tools, search tools, dividend tools, and order tools, making reliable tool selection very difficult.

Naming Consistency1/5

Naming conventions are wildly inconsistent: some tools use verb_noun, some use noun_verb, some are prefixed schwab_ or unified_, and some end in _tool. Similar operations use different verbs and structures, such as buy_stock_market, schwab_buy_stock_limit, schwab_order_buy_option_limit, and cancel_all_option_orders_tool.

Tool Count1/5

150 tools is an extreme count for an MCP server, far beyond what an agent can reasonably navigate. The high count is largely caused by redundant variants and broker-specific duplicates rather than genuinely distinct capabilities.

Completeness3/5

The server does cover a broad range of brokerage functionality: stock and option trading, orders, positions, watchlists, market data, dividends, transactions, and account info. However, there are notable gaps and rough edges, such as no clear watchlist create/delete lifecycle, several undocumented helper tools, and inconsistent coverage between Robinhood and Schwab.

Maintenance

ActivitySlowing
ResponsivenessWithin a week