# E*TRADE MCP Server - Comprehensive Implementation Plan
## Executive Summary
This document outlines a comprehensive plan to implement a Model Context Protocol (MCP) server on top of the existing E*TRADE Python client. The MCP server will enable LLMs (like Claude) to interact with E*TRADE's trading platform APIs through a standardized interface, providing capabilities for market data retrieval, account management, portfolio tracking, and order operations.
---
## 1. Project Overview
### 1.1 Objectives
- Create an MCP server that exposes E*TRADE API functionality to LLMs
- Provide safe, controlled access to trading operations with appropriate guardrails
- Enable natural language interaction with brokerage accounts and market data
- Maintain security best practices for handling financial credentials and operations
### 1.2 Technology Stack
- **Language**: Python 3.10+
- **MCP SDK**: `@modelcontextprotocol/python-sdk` (v1.2.0+)
- **Package Manager**: `uv` for dependency management
- **Authentication**: OAuth 1.0 (existing E*TRADE implementation)
- **Transport**: stdio (for local Claude Desktop) and SSE/HTTP (for remote access)
---
## 2. Architecture Design
### 2.1 High-Level Architecture
```
┌─────────────────┐
│ LLM Client │
│ (Claude) │
└────────┬────────┘
│ MCP Protocol (JSON-RPC)
│
┌────────▼────────────────────────┐
│ MCP Server Layer │
│ - Tool Definitions │
│ - Resource Handlers │
│ - Prompt Templates │
│ - Authorization & Safety │
└────────┬────────────────────────┘
│
┌────────▼────────────────────────┐
│ E*TRADE Client Wrapper │
│ - Session Management │
│ - OAuth Token Refresh │
│ - Rate Limiting │
│ - Error Handling │
└────────┬────────────────────────┘
│
┌────────▼────────────────────────┐
│ Existing E*TRADE Client │
│ - accounts/ │
│ - market/ │
│ - order/ │
└─────────────────────────────────┘
```
### 2.2 Module Structure
```
etrade-mcp/
├── client/ # Existing E*TRADE client
│ └── src/
├── server/ # New MCP server
│ ├── __init__.py
│ ├── main.py # MCP server entry point
│ ├── auth/
│ │ ├── __init__.py
│ │ ├── oauth_manager.py # OAuth session management
│ │ └── token_store.py # Secure token persistence
│ ├── tools/
│ │ ├── __init__.py
│ │ ├── market_tools.py # Market data tools
│ │ ├── account_tools.py # Account info tools
│ │ ├── portfolio_tools.py # Portfolio tools
│ │ └── order_tools.py # Order management tools
│ ├── resources/
│ │ ├── __init__.py
│ │ └── account_resources.py
│ ├── prompts/
│ │ ├── __init__.py
│ │ └── trading_prompts.py
│ ├── safety/
│ │ ├── __init__.py
│ │ ├── validators.py # Input validation
│ │ ├── rate_limiter.py # Rate limiting
│ │ └── risk_checks.py # Trading risk checks
│ └── config.py # Server configuration
├── tests/
│ ├── test_tools.py
│ ├── test_auth.py
│ └── test_safety.py
├── docs/
│ └── ai_dev/
│ └── mcp-server-implementation-plan.md
├── pyproject.toml
└── README.md
```
---
## 3. MCP Primitives Design
### 3.1 Tools (LLM-Controlled Functions)
#### 3.1.1 Market Data Tools
**Tool: `get_stock_quote`**
```python
{
"name": "get_stock_quote",
"description": "Get real-time or delayed quote for a stock symbol",
"inputSchema": {
"type": "object",
"properties": {
"symbol": {
"type": "string",
"description": "Stock symbol (e.g., AAPL, MSFT)"
}
},
"required": ["symbol"]
}
}
```
**Tool: `get_multiple_quotes`**
```python
{
"name": "get_multiple_quotes",
"description": "Get quotes for multiple symbols",
"inputSchema": {
"type": "object",
"properties": {
"symbols": {
"type": "array",
"items": {"type": "string"},
"description": "List of stock symbols",
"maxItems": 25
}
},
"required": ["symbols"]
}
}
```
#### 3.1.2 Account Tools
**Tool: `list_accounts`**
```python
{
"name": "list_accounts",
"description": "List all E*TRADE accounts for the authenticated user",
"inputSchema": {
"type": "object",
"properties": {}
}
}
```
**Tool: `get_account_balance`**
```python
{
"name": "get_account_balance",
"description": "Get balance and buying power for a specific account",
"inputSchema": {
"type": "object",
"properties": {
"account_id_key": {
"type": "string",
"description": "Account ID key from list_accounts"
}
},
"required": ["account_id_key"]
}
}
```
#### 3.1.3 Portfolio Tools
**Tool: `get_portfolio`**
```python
{
"name": "get_portfolio",
"description": "Get all positions in an account",
"inputSchema": {
"type": "object",
"properties": {
"account_id_key": {
"type": "string",
"description": "Account ID key"
}
},
"required": ["account_id_key"]
}
}
```
**Tool: `get_position_details`**
```python
{
"name": "get_position_details",
"description": "Get detailed information about a specific position",
"inputSchema": {
"type": "object",
"properties": {
"account_id_key": {"type": "string"},
"symbol": {"type": "string"}
},
"required": ["account_id_key", "symbol"]
}
}
```
#### 3.1.4 Order Tools (Read-Only Initially)
**Tool: `list_orders`**
```python
{
"name": "list_orders",
"description": "List orders by status (open, executed, cancelled, etc.)",
"inputSchema": {
"type": "object",
"properties": {
"account_id_key": {"type": "string"},
"status": {
"type": "string",
"enum": ["OPEN", "EXECUTED", "CANCELLED", "REJECTED", "EXPIRED"],
"description": "Order status filter"
}
},
"required": ["account_id_key", "status"]
}
}
```
**Tool: `preview_order`** (Phase 2 - with safety checks)
```python
{
"name": "preview_order",
"description": "Preview an order without placing it (requires explicit user confirmation)",
"inputSchema": {
"type": "object",
"properties": {
"account_id_key": {"type": "string"},
"symbol": {"type": "string"},
"order_action": {
"type": "string",
"enum": ["BUY", "SELL", "BUY_TO_COVER", "SELL_SHORT"]
},
"quantity": {"type": "integer", "minimum": 1},
"price_type": {
"type": "string",
"enum": ["MARKET", "LIMIT"]
},
"limit_price": {"type": "number", "minimum": 0},
"order_term": {
"type": "string",
"enum": ["GOOD_FOR_DAY", "IMMEDIATE_OR_CANCEL", "FILL_OR_KILL"]
}
},
"required": ["account_id_key", "symbol", "order_action", "quantity", "price_type"]
}
}
```
**Note**: Order placement and cancellation tools will require additional safety mechanisms (see Section 5).
### 3.2 Resources (Application-Controlled Data)
**Resource: `account://{account_id_key}/summary`**
- Provides read-only account summary (balance, buying power, positions count)
- Updated periodically and cached
**Resource: `portfolio://{account_id_key}/positions`**
- Structured list of all positions
- Includes P&L, cost basis, current value
**Resource: `market://watchlist/{name}`**
- User-defined watchlist with quotes
- Can be configured in server settings
**Resource: `orders://{account_id_key}/recent`**
- Recent order history (last 30 days)
- Formatted for analysis
### 3.3 Prompts (User-Controlled Templates)
**Prompt: `portfolio_analysis`**
```python
{
"name": "portfolio_analysis",
"description": "Analyze portfolio holdings and provide insights",
"arguments": [
{
"name": "account_id_key",
"description": "Account to analyze",
"required": True
}
]
}
```
- Pre-configured prompt that guides LLM to analyze portfolio
- Uses get_portfolio and get_account_balance tools
- Provides sector diversification, P&L analysis, risk assessment
**Prompt: `market_summary`**
```python
{
"name": "market_summary",
"description": "Get summary of specified stocks",
"arguments": [
{
"name": "symbols",
"description": "Comma-separated stock symbols",
"required": True
}
]
}
```
**Prompt: `trade_idea_analysis`**
```python
{
"name": "trade_idea_analysis",
"description": "Analyze a potential trade idea (educational only)",
"arguments": [
{
"name": "symbol",
"required": True
},
{
"name": "strategy",
"description": "Trade strategy to analyze",
"required": True
}
]
}
```
---
## 4. Authentication & Session Management
### 4.1 OAuth Flow Adaptation
**Challenge**: The existing client uses interactive OAuth with browser-based authorization.
**Solution**: Implement persistent token storage with refresh capability.
**Implementation Steps**:
1. **Initial Authorization** (one-time setup):
```python
# Run standalone auth script
python -m server.auth.setup_oauth
```
- Opens browser for OAuth authorization
- Stores access token and secret securely
- Encrypts tokens using system keyring or environment-specific encryption
2. **Token Storage**:
```python
# server/auth/token_store.py
class TokenStore:
def save_tokens(self, access_token, access_secret):
# Store in encrypted file or system keyring
pass
def load_tokens(self):
# Retrieve and decrypt tokens
pass
def is_valid(self):
# Check token expiration
pass
```
3. **Session Manager**:
```python
# server/auth/oauth_manager.py
class OAuthSessionManager:
def get_session(self):
# Load tokens from storage
# Create OAuth session
# Handle token refresh if needed
pass
def refresh_if_needed(self):
# E*TRADE tokens expire, implement refresh logic
pass
```
### 4.2 Configuration Management
```python
# server/config.py
from pydantic import BaseModel
from typing import Literal
class ETradeMCPConfig(BaseModel):
consumer_key: str
consumer_secret: str
environment: Literal["sandbox", "production"] = "sandbox"
base_url: str
# Safety settings
max_order_value: float = 10000.0 # Max single order value
require_confirmation: bool = True # Require user confirmation for trades
read_only_mode: bool = True # Disable order placement initially
# Rate limiting
requests_per_minute: int = 60
@classmethod
def from_env(cls):
# Load from environment variables
pass
@classmethod
def from_file(cls, path: str):
# Load from config file
pass
```
---
## 5. Safety & Risk Management
### 5.1 Input Validation
```python
# server/safety/validators.py
class OrderValidator:
def validate_symbol(self, symbol: str) -> bool:
# Check symbol format (uppercase, valid characters)
# Optionally validate against known symbols
pass
def validate_quantity(self, quantity: int, max_quantity: int = 1000) -> bool:
# Prevent excessively large orders
pass
def validate_price(self, price: float, symbol: str) -> bool:
# Check price is within reasonable range
# Compare to current market price (±50%)
pass
def validate_order_value(self, quantity: int, price: float, max_value: float) -> bool:
# Ensure order value doesn't exceed limits
pass
```
### 5.2 Rate Limiting
```python
# server/safety/rate_limiter.py
from datetime import datetime, timedelta
from collections import deque
class RateLimiter:
def __init__(self, max_requests: int, window_seconds: int):
self.max_requests = max_requests
self.window = timedelta(seconds=window_seconds)
self.requests = deque()
def allow_request(self) -> bool:
now = datetime.now()
# Remove old requests outside window
while self.requests and self.requests[0] < now - self.window:
self.requests.popleft()
if len(self.requests) >= self.max_requests:
return False
self.requests.append(now)
return True
```
### 5.3 Risk Checks (Phase 2)
```python
# server/safety/risk_checks.py
class RiskChecker:
def check_buying_power(self, account_balance, order_value) -> tuple[bool, str]:
# Ensure sufficient buying power
pass
def check_position_limits(self, portfolio, symbol, new_quantity) -> tuple[bool, str]:
# Prevent over-concentration in single position
pass
def check_daily_limits(self, account_id, proposed_trades) -> tuple[bool, str]:
# Limit number of trades per day
pass
def check_volatility_warning(self, symbol) -> tuple[bool, str]:
# Warn about highly volatile stocks
pass
```
### 5.4 User Confirmation Flow
For critical operations (order placement, cancellation), implement confirmation:
```python
# Confirmation required before execution
@mcp.tool()
async def place_order_confirmed(
account_id_key: str,
order_preview_id: str,
confirmation_code: str
) -> str:
"""
Place an order after explicit user confirmation.
User must first preview order, then confirm with code.
"""
# Verify confirmation code matches preview
# Execute order
# Return execution details
pass
```
---
## 6. Implementation Phases
### Phase 1: Read-Only MCP Server (Week 1-2)
**Goal**: Enable safe data retrieval and analysis
**Tasks**:
1. Set up project structure with `uv` and MCP SDK
2. Implement OAuth token storage and session management
3. Create market data tools:
- `get_stock_quote`
- `get_multiple_quotes`
4. Create account tools (read-only):
- `list_accounts`
- `get_account_balance`
- `get_portfolio`
5. Implement resources:
- Account summaries
- Portfolio positions
6. Create basic prompts:
- Portfolio analysis
- Market summary
7. Write unit tests for all tools
8. Test with Claude Desktop using stdio transport
**Deliverables**:
- Working read-only MCP server
- Configuration guide
- User documentation
### Phase 2: Order Preview & Analysis (Week 3)
**Goal**: Enable order preview without execution
**Tasks**:
1. Implement order viewing tools:
- `list_orders`
- `get_order_details`
2. Add order preview tool:
- `preview_order` (no execution)
3. Implement safety validators
4. Add rate limiting
5. Create order analysis prompts
6. Comprehensive testing with sandbox environment
**Deliverables**:
- Order preview functionality
- Safety validation layer
- Enhanced documentation
### Phase 3: Order Execution with Safeguards (Week 4-5)
**Goal**: Enable controlled order placement
**Tasks**:
1. Implement confirmation flow:
- Preview → Confirmation code → Execution
2. Add risk checks:
- Buying power verification
- Position limits
- Daily trade limits
3. Implement order placement tool:
- `place_order_confirmed`
4. Add order cancellation tool:
- `cancel_order_confirmed`
5. Create audit logging
6. Extensive testing with small orders in sandbox
7. Production readiness review
**Deliverables**:
- Full order execution capability
- Comprehensive safety system
- Audit logging
- Production deployment guide
### Phase 4: Advanced Features (Week 6+)
**Goal**: Enhanced functionality and user experience
**Tasks**:
1. Add HTTP/SSE transport for remote access
2. Implement caching for market data
3. Add portfolio analytics:
- Performance metrics
- Sector allocation
- Risk metrics
4. Create advanced prompts:
- Tax-loss harvesting analysis
- Rebalancing suggestions
5. Add webhook notifications for order fills
6. Performance optimization
7. Enhanced error handling and retry logic
**Deliverables**:
- Remote access capability
- Advanced analytics
- Optimized performance
---
## 7. Technical Implementation Details
### 7.1 MCP Server Entry Point
```python
# server/main.py
import asyncio
from mcp.server import Server
from mcp.server.stdio import stdio_server
from server.tools.market_tools import MarketTools
from server.tools.account_tools import AccountTools
from server.auth.oauth_manager import OAuthSessionManager
from server.config import ETradeMCPConfig
async def main():
# Load configuration
config = ETradeMCPConfig.from_env()
# Initialize OAuth session manager
session_manager = OAuthSessionManager(config)
# Create MCP server
server = Server("etrade-mcp")
# Initialize tool modules
market_tools = MarketTools(session_manager)
account_tools = AccountTools(session_manager)
# Register tools
@server.list_tools()
async def list_tools():
return [
market_tools.get_quote_tool_def(),
account_tools.list_accounts_tool_def(),
account_tools.get_balance_tool_def(),
# ... more tools
]
@server.call_tool()
async def call_tool(name: str, arguments: dict):
if name == "get_stock_quote":
return await market_tools.get_quote(arguments["symbol"])
elif name == "list_accounts":
return await account_tools.list_accounts()
elif name == "get_account_balance":
return await account_tools.get_balance(arguments["account_id_key"])
# ... handle all tools
# Run server with stdio transport
async with stdio_server() as (read_stream, write_stream):
await server.run(
read_stream,
write_stream,
server.create_initialization_options()
)
if __name__ == "__main__":
asyncio.run(main())
```
### 7.2 Tool Implementation Example
```python
# server/tools/market_tools.py
from mcp.types import Tool, TextContent
import json
class MarketTools:
def __init__(self, session_manager):
self.session_manager = session_manager
def get_quote_tool_def(self) -> Tool:
return Tool(
name="get_stock_quote",
description="Get real-time quote for a stock symbol",
inputSchema={
"type": "object",
"properties": {
"symbol": {
"type": "string",
"description": "Stock symbol (e.g., AAPL)"
}
},
"required": ["symbol"]
}
)
async def get_quote(self, symbol: str) -> list[TextContent]:
# Get OAuth session
session = await self.session_manager.get_session()
base_url = self.session_manager.config.base_url
# Call E*TRADE API
url = f"{base_url}/v1/market/quote/{symbol}.json"
response = session.get(url)
if response.status_code != 200:
return [TextContent(
type="text",
text=f"Error fetching quote: {response.status_code}"
)]
data = response.json()
# Extract and format quote data
quote_data = self._format_quote(data)
return [TextContent(
type="text",
text=json.dumps(quote_data, indent=2)
)]
def _format_quote(self, data: dict) -> dict:
# Extract relevant quote information
if "QuoteResponse" not in data or "QuoteData" not in data["QuoteResponse"]:
return {"error": "Invalid quote response"}
quote = data["QuoteResponse"]["QuoteData"][0]
return {
"symbol": quote.get("Product", {}).get("symbol"),
"last_price": quote.get("All", {}).get("lastTrade"),
"change": quote.get("All", {}).get("changeClose"),
"change_percent": quote.get("All", {}).get("changeClosePercentage"),
"bid": quote.get("All", {}).get("bid"),
"ask": quote.get("All", {}).get("ask"),
"volume": quote.get("All", {}).get("totalVolume"),
"timestamp": quote.get("dateTime")
}
```
### 7.3 Logging Configuration
```python
# server/logging_config.py
import logging
import sys
def setup_logging(log_file: str = "etrade_mcp.log"):
"""
Configure logging for MCP server.
IMPORTANT: Use stderr for STDIO transport, not stdout.
"""
logger = logging.getLogger("etrade_mcp")
logger.setLevel(logging.DEBUG)
# File handler for detailed logs
file_handler = logging.FileHandler(log_file)
file_handler.setLevel(logging.DEBUG)
# Stderr handler for console output (not stdout!)
console_handler = logging.StreamHandler(sys.stderr)
console_handler.setLevel(logging.INFO)
# Formatter
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
file_handler.setFormatter(formatter)
console_handler.setFormatter(formatter)
logger.addHandler(file_handler)
logger.addHandler(console_handler)
return logger
```
---
## 8. Testing Strategy
### 8.1 Unit Tests
```python
# tests/test_market_tools.py
import pytest
from unittest.mock import Mock, patch
from server.tools.market_tools import MarketTools
@pytest.fixture
def mock_session_manager():
manager = Mock()
manager.config.base_url = "https://apisb.etrade.com"
return manager
@pytest.mark.asyncio
async def test_get_quote_success(mock_session_manager):
tools = MarketTools(mock_session_manager)
# Mock successful API response
mock_response = Mock()
mock_response.status_code = 200
mock_response.json.return_value = {
"QuoteResponse": {
"QuoteData": [{
"Product": {"symbol": "AAPL"},
"All": {"lastTrade": 150.25}
}]
}
}
with patch.object(tools.session_manager, 'get_session') as mock_get_session:
mock_session = Mock()
mock_session.get.return_value = mock_response
mock_get_session.return_value = mock_session
result = await tools.get_quote("AAPL")
assert result[0].type == "text"
assert "150.25" in result[0].text
```
### 8.2 Integration Tests
```python
# tests/test_integration.py
import pytest
from server.main import create_server
from mcp.client import Client
@pytest.mark.integration
@pytest.mark.asyncio
async def test_full_quote_workflow():
# Test complete flow from client request to response
server = create_server()
client = Client()
# Test list tools
tools = await client.list_tools()
assert any(t.name == "get_stock_quote" for t in tools)
# Test call tool
result = await client.call_tool("get_stock_quote", {"symbol": "AAPL"})
assert result is not None
```
### 8.3 Safety Tests
```python
# tests/test_safety.py
import pytest
from server.safety.validators import OrderValidator
def test_validate_quantity_within_limits():
validator = OrderValidator()
assert validator.validate_quantity(100, max_quantity=1000) == True
assert validator.validate_quantity(2000, max_quantity=1000) == False
def test_validate_order_value():
validator = OrderValidator()
# 100 shares at $150 = $15,000 (exceeds $10,000 limit)
assert validator.validate_order_value(100, 150.0, max_value=10000.0) == False
# 50 shares at $150 = $7,500 (within limit)
assert validator.validate_order_value(50, 150.0, max_value=10000.0) == True
```
---
## 9. Deployment & Configuration
### 9.1 Installation
```bash
# Clone repository
git clone <repo-url>
cd etrade-mcp
# Install uv package manager
curl -LsSf https://astral.sh/uv/install.sh | sh
# Create virtual environment and install dependencies
uv venv
source .venv/bin/activate # or .venv\Scripts\activate on Windows
uv pip install -e ".[dev]"
```
### 9.2 Initial Setup
```bash
# Run OAuth setup (one-time)
python -m server.auth.setup_oauth
# Follow prompts to:
# 1. Select environment (sandbox/production)
# 2. Authorize in browser
# 3. Enter verification code
# 4. Tokens are encrypted and stored
```
### 9.3 Claude Desktop Configuration
Add to Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json` on Mac):
```json
{
"mcpServers": {
"etrade": {
"command": "uv",
"args": [
"--directory",
"/path/to/etrade-mcp",
"run",
"etrade-mcp"
],
"env": {
"ETRADE_ENVIRONMENT": "sandbox",
"ETRADE_READ_ONLY": "true"
}
}
}
}
```
### 9.4 Environment Variables
```bash
# .env file
ETRADE_CONSUMER_KEY=your_key_here
ETRADE_CONSUMER_SECRET=your_secret_here
ETRADE_ENVIRONMENT=sandbox # or production
ETRADE_READ_ONLY=true # Set to false to enable order placement
ETRADE_MAX_ORDER_VALUE=10000.0
ETRADE_REQUESTS_PER_MINUTE=60
```
---
## 10. Security Considerations
### 10.1 Credential Management
- Never commit credentials to version control
- Use environment variables or encrypted storage
- Implement token rotation and refresh
- Use system keyring for production deployments
### 10.2 API Security
- Implement rate limiting to prevent abuse
- Validate all inputs before API calls
- Use HTTPS for all E*TRADE API communication
- Log all order-related operations for audit
### 10.3 Trading Safety
- Start with read-only mode by default
- Require explicit user confirmation for trades
- Implement position and value limits
- Add circuit breakers for suspicious activity
- Sandbox testing before production use
### 10.4 Data Privacy
- Don't log sensitive account information
- Sanitize responses before returning to LLM
- Implement data retention policies
- Allow users to opt out of logging
---
## 11. Documentation Requirements
### 11.1 User Documentation
- Installation guide
- Configuration guide
- Available tools reference
- Safety features explanation
- Troubleshooting guide
- FAQ
### 11.2 Developer Documentation
- Architecture overview
- API reference
- Contributing guidelines
- Testing procedures
- Deployment guide
### 11.3 Examples
- Portfolio analysis conversation
- Market research queries
- Order preview workflow
- Risk assessment scenarios
---
## 12. Success Metrics
### 12.1 Functional Metrics
- All read-only tools working reliably
- Order preview accuracy: 100%
- API error rate: < 1%
- Average response time: < 2 seconds
### 12.2 Safety Metrics
- Zero unauthorized trades
- All trades require confirmation
- Rate limiting effective
- Input validation: 100% coverage
### 12.3 User Experience
- Clear error messages
- Natural language interaction
- Helpful tool descriptions
- Prompt templates useful
---
## 13. Future Enhancements
### 13.1 Advanced Features
- Options trading support
- Multi-leg order strategies
- Conditional orders
- Streaming real-time quotes
- Technical analysis tools
- News and research integration
### 13.2 AI Capabilities
- Portfolio optimization suggestions
- Tax-loss harvesting recommendations
- Risk analysis and alerts
- Pattern recognition in trading history
- Automated rebalancing proposals
### 13.3 Integration
- Multiple broker support
- Aggregated portfolio view
- Integration with financial planning tools
- Export to accounting software
---
## 14. Risk Disclaimer
**IMPORTANT**: This MCP server is designed for educational and informational purposes.
- Trading involves risk of loss
- Past performance doesn't guarantee future results
- LLM suggestions are not financial advice
- Users are responsible for all trading decisions
- Always verify trades before execution
- Start with paper trading or small positions
- Consult financial advisors for investment decisions
---
## 15. Next Steps
### Immediate Actions:
1. ✅ Review and approve this implementation plan
2. Set up development environment
3. Implement Phase 1 (Read-Only Server)
4. Test with Claude Desktop
5. Gather feedback and iterate
### Timeline:
- **Week 1-2**: Phase 1 - Read-only functionality
- **Week 3**: Phase 2 - Order preview
- **Week 4-5**: Phase 3 - Order execution with safeguards
- **Week 6+**: Phase 4 - Advanced features
### Resources Needed:
- E*TRADE sandbox account
- E*TRADE API credentials
- Python development environment
- Claude Desktop for testing
- Documentation time
---
## Appendix A: Dependencies
```toml
# pyproject.toml
[project]
name = "etrade-mcp"
version = "0.1.0"
description = "MCP Server for E*TRADE API"
requires-python = ">=3.10"
dependencies = [
"mcp>=1.2.0",
"rauth>=0.7.3",
"pydantic>=2.0.0",
"pydantic-settings>=2.0.0",
"python-dotenv>=1.0.0",
"cryptography>=41.0.0",
"aiohttp>=3.9.0",
]
[project.optional-dependencies]
dev = [
"pytest>=7.4.0",
"pytest-asyncio>=0.21.0",
"pytest-cov>=4.1.0",
"black>=23.0.0",
"ruff>=0.1.0",
"mypy>=1.7.0",
]
[project.scripts]
etrade-mcp = "server.main:main"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
```
---
## Appendix B: Example Conversations
### Example 1: Portfolio Analysis
```
User: "Analyze my E*TRADE portfolio"
Claude: I'll analyze your portfolio. Let me first get your accounts.
[Uses: list_accounts]
I see you have a Brokerage account. Let me get the details.
[Uses: get_portfolio, get_account_balance]
Your portfolio analysis:
- Total Value: $45,230.15
- Cash Available: $5,120.00
- Positions: 8
- Top Holdings:
1. AAPL - 50 shares ($7,550.00, +12.3%)
2. MSFT - 30 shares ($11,250.00, +8.7%)
...
Your portfolio shows good diversification across tech and healthcare sectors...
```
### Example 2: Order Preview
```
User: "What would it cost to buy 10 shares of AAPL?"
Claude: Let me check the current price and preview this order.
[Uses: get_stock_quote, preview_order]
Current AAPL price: $151.25
Order Preview:
- Action: BUY
- Quantity: 10 shares
- Type: MARKET
- Estimated Cost: $1,512.50
- Estimated Commission: $0.00
- Total: $1,512.50
Your current buying power: $5,120.00
This order would use 29.5% of your available cash. Would you like to proceed with placing this order?
⚠️ Note: This is a preview only. I cannot execute trades without your explicit confirmation.
```
---
## Conclusion
This implementation plan provides a comprehensive roadmap for building a safe, functional MCP server on top of the E*TRADE Python client. The phased approach ensures that safety and reliability are prioritized, starting with read-only operations and gradually adding order execution capabilities with appropriate safeguards.
The architecture is designed to be extensible, maintainable, and secure, following MCP best practices and incorporating robust error handling, validation, and audit logging. With proper implementation, this MCP server will enable powerful natural language interaction with E*TRADE accounts while maintaining the highest standards of safety and user control.