Loading...
Loading...
Build AI-powered trading strategies and execute stock, crypto, and options trades using Alpaca's official MCP server with natural language commands
npx skill4agent add aradotso/mcp-skills alpaca-trading-mcp-serverSkill by ara.so — MCP Skills collection.
uvAPI_KEYSECRET_KEY~/Library/Application Support/Claude/claude_desktop_config.json%APPDATA%\Claude\claude_desktop_config.json{
"mcpServers": {
"alpaca": {
"command": "uvx",
"args": ["alpaca-mcp-server"],
"env": {
"ALPACA_API_KEY": "your_alpaca_api_key",
"ALPACA_SECRET_KEY": "your_alpaca_secret_key",
"ALPACA_PAPER_TRADE": "true"
}
}
}
}~/.cursor/mcp.json{
"mcpServers": {
"alpaca": {
"command": "uvx",
"args": ["alpaca-mcp-server"],
"env": {
"ALPACA_API_KEY": "your_alpaca_api_key",
"ALPACA_SECRET_KEY": "your_alpaca_secret_key",
"ALPACA_PAPER_TRADE": "true"
}
}
}
}.vscode/mcp.json{
"mcp": {
"servers": {
"alpaca": {
"type": "stdio",
"command": "uvx",
"args": ["alpaca-mcp-server"],
"env": {
"ALPACA_API_KEY": "your_alpaca_api_key",
"ALPACA_SECRET_KEY": "your_alpaca_secret_key",
"ALPACA_PAPER_TRADE": "true"
}
}
}
}
}# Clone repository
git clone https://github.com/alpacahq/alpaca-mcp-server.git
cd alpaca-mcp-server
# Build image
docker build -t mcp/alpaca:latest .
# Add to MCP client config
{
"mcpServers": {
"alpaca": {
"command": "docker",
"args": [
"run", "--rm", "-i",
"-e", "ALPACA_API_KEY",
"-e", "ALPACA_SECRET_KEY",
"-e", "ALPACA_PAPER_TRADE=true",
"mcp/alpaca:latest"
]
}
}
}| Variable | Required | Default | Description |
|---|---|---|---|
| Yes | — | Your Alpaca API key |
| Yes | — | Your Alpaca secret key |
| No | | Use paper trading ( |
| No | all | Comma-separated toolsets to enable |
ALPACA_TOOLSETS{
"env": {
"ALPACA_API_KEY": "...",
"ALPACA_SECRET_KEY": "...",
"ALPACA_TOOLSETS": "account,trading,stock-data"
}
}accounttradingwatchlistsassetsstock-datacrypto-dataoptions-datacorporate-actionsnews{
"env": {
"ALPACA_API_KEY": "your_live_api_key",
"ALPACA_SECRET_KEY": "your_live_secret_key",
"ALPACA_PAPER_TRADE": "false"
}
}import asyncio
from alpaca.trading.client import TradingClient
from alpaca.data.historical import StockHistoricalDataClient
from alpaca.data.requests import StockBarsRequest
from alpaca.data.timeframe import TimeFrame
from datetime import datetime, timedelta
# Initialize clients with environment variables
trading_client = TradingClient(
api_key=os.getenv('ALPACA_API_KEY'),
secret_key=os.getenv('ALPACA_SECRET_KEY'),
paper=os.getenv('ALPACA_PAPER_TRADE', 'true').lower() == 'true'
)
data_client = StockHistoricalDataClient(
api_key=os.getenv('ALPACA_API_KEY'),
secret_key=os.getenv('ALPACA_SECRET_KEY')
)
# Get account information
account = trading_client.get_account()
print(f"Buying Power: ${account.buying_power}")
print(f"Cash: ${account.cash}")
# Fetch historical stock data
request_params = StockBarsRequest(
symbol_or_symbols=["AAPL", "TSLA"],
timeframe=TimeFrame.Day,
start=datetime.now() - timedelta(days=30),
end=datetime.now()
)
bars = data_client.get_stock_bars(request_params)
for symbol, bar_data in bars.items():
print(f"{symbol}: {len(bar_data)} bars")from alpaca.trading.requests import MarketOrderRequest, LimitOrderRequest
from alpaca.trading.enums import OrderSide, TimeInForce
# Market order
market_order_data = MarketOrderRequest(
symbol="AAPL",
qty=10,
side=OrderSide.BUY,
time_in_force=TimeInForce.DAY
)
market_order = trading_client.submit_order(market_order_data)
print(f"Market order placed: {market_order.id}")
# Limit order
limit_order_data = LimitOrderRequest(
symbol="TSLA",
limit_price=250.00,
qty=5,
side=OrderSide.SELL,
time_in_force=TimeInForce.GTC
)
limit_order = trading_client.submit_order(limit_order_data)
print(f"Limit order placed: {limit_order.id}")from alpaca.trading.requests import GetOptionContractsRequest
from alpaca.trading.enums import ContractType
from datetime import datetime, timedelta
# Find option contracts
option_request = GetOptionContractsRequest(
underlying_symbols=["AAPL"],
expiration_date_gte=datetime.now().date(),
expiration_date_lte=(datetime.now() + timedelta(days=60)).date(),
type=ContractType.CALL,
strike_price_gte=170,
strike_price_lte=180
)
contracts = trading_client.get_option_contracts(option_request)
for contract in contracts:
print(f"{contract.symbol}: Strike ${contract.strike_price}, "
f"Expires {contract.expiration_date}")from alpaca.data.live import StockDataStream
# Initialize streaming client
stream = StockDataStream(
api_key=os.getenv('ALPACA_API_KEY'),
secret_key=os.getenv('ALPACA_SECRET_KEY')
)
# Define handlers
async def quote_handler(data):
print(f"{data.symbol}: Bid ${data.bid_price} Ask ${data.ask_price}")
async def trade_handler(data):
print(f"{data.symbol}: Trade ${data.price} Size {data.size}")
# Subscribe to streams
stream.subscribe_quotes(quote_handler, "AAPL", "TSLA")
stream.subscribe_trades(trade_handler, "AAPL", "TSLA")
# Run stream
stream.run()from alpaca.trading.client import TradingClient
from alpaca.data.historical import StockHistoricalDataClient
from alpaca.data.requests import StockBarsRequest
from alpaca.data.timeframe import TimeFrame
from alpaca.trading.requests import MarketOrderRequest
from alpaca.trading.enums import OrderSide, TimeInForce
from datetime import datetime, timedelta
import pandas as pd
class SimpleMomentumBot:
def __init__(self, api_key, secret_key, paper=True):
self.trading_client = TradingClient(api_key, secret_key, paper=paper)
self.data_client = StockHistoricalDataClient(api_key, secret_key)
def get_momentum(self, symbol, days=10):
"""Calculate simple momentum indicator"""
request = StockBarsRequest(
symbol_or_symbols=[symbol],
timeframe=TimeFrame.Day,
start=datetime.now() - timedelta(days=days*2),
end=datetime.now()
)
bars = self.data_client.get_stock_bars(request)
df = bars.df.reset_index()
# Calculate momentum: % change over period
current_price = df['close'].iloc[-1]
past_price = df['close'].iloc[-days]
return ((current_price - past_price) / past_price) * 100
def execute_strategy(self, symbol, threshold=5.0):
"""Buy if momentum > threshold, sell if momentum < -threshold"""
momentum = self.get_momentum(symbol)
position = self.get_position(symbol)
if momentum > threshold and position is None:
# Buy signal
order = MarketOrderRequest(
symbol=symbol,
qty=10,
side=OrderSide.BUY,
time_in_force=TimeInForce.DAY
)
return self.trading_client.submit_order(order)
elif momentum < -threshold and position is not None:
# Sell signal
return self.trading_client.close_position(symbol)
def get_position(self, symbol):
"""Get current position for symbol"""
try:
return self.trading_client.get_open_position(symbol)
except:
return None
# Usage
bot = SimpleMomentumBot(
api_key=os.getenv('ALPACA_API_KEY'),
secret_key=os.getenv('ALPACA_SECRET_KEY'),
paper=True
)
order = bot.execute_strategy("AAPL", threshold=5.0)from alpaca.trading.client import TradingClient
import pandas as pd
def analyze_portfolio(api_key, secret_key, paper=True):
"""Analyze current portfolio holdings"""
client = TradingClient(api_key, secret_key, paper=paper)
# Get account and positions
account = client.get_account()
positions = client.get_all_positions()
# Calculate metrics
total_equity = float(account.equity)
positions_data = []
for position in positions:
positions_data.append({
'Symbol': position.symbol,
'Qty': float(position.qty),
'Avg Entry': float(position.avg_entry_price),
'Current Price': float(position.current_price),
'Market Value': float(position.market_value),
'P&L': float(position.unrealized_pl),
'P&L %': float(position.unrealized_plpc) * 100,
'Weight %': (float(position.market_value) / total_equity) * 100
})
df = pd.DataFrame(positions_data)
print(f"\nPortfolio Summary")
print(f"Total Equity: ${total_equity:,.2f}")
print(f"Cash: ${float(account.cash):,.2f}")
print(f"Buying Power: ${float(account.buying_power):,.2f}")
print(f"\nPositions:")
print(df.to_string(index=False))
print(f"\nTotal P&L: ${df['P&L'].sum():,.2f}")
return df
# Usage
df = analyze_portfolio(
api_key=os.getenv('ALPACA_API_KEY'),
secret_key=os.getenv('ALPACA_SECRET_KEY')
)from alpaca.trading.client import TradingClient
class RiskManager:
def __init__(self, api_key, secret_key, paper=True):
self.client = TradingClient(api_key, secret_key, paper=paper)
def check_position_limits(self, symbol, qty, max_position_pct=10):
"""Verify position doesn't exceed maximum portfolio percentage"""
account = self.client.get_account()
total_equity = float(account.equity)
# Get current price
from alpaca.data.historical import StockHistoricalDataClient
from alpaca.data.requests import StockLatestQuoteRequest
data_client = StockHistoricalDataClient(
self.client.api_key,
self.client.secret_key
)
request = StockLatestQuoteRequest(symbol_or_symbols=[symbol])
quote = data_client.get_stock_latest_quote(request)[symbol]
position_value = float(qty) * float(quote.ask_price)
position_pct = (position_value / total_equity) * 100
if position_pct > max_position_pct:
raise ValueError(
f"Position would be {position_pct:.1f}% of portfolio, "
f"exceeds {max_position_pct}% limit"
)
return True
def check_buying_power(self, symbol, qty):
"""Verify sufficient buying power for trade"""
account = self.client.get_account()
# Get current price
from alpaca.data.historical import StockHistoricalDataClient
from alpaca.data.requests import StockLatestQuoteRequest
data_client = StockHistoricalDataClient(
self.client.api_key,
self.client.secret_key
)
request = StockLatestQuoteRequest(symbol_or_symbols=[symbol])
quote = data_client.get_stock_latest_quote(request)[symbol]
cost = float(qty) * float(quote.ask_price)
buying_power = float(account.buying_power)
if cost > buying_power:
raise ValueError(
f"Insufficient buying power. Cost: ${cost:.2f}, "
f"Available: ${buying_power:.2f}"
)
return True
# Usage
risk_mgr = RiskManager(
api_key=os.getenv('ALPACA_API_KEY'),
secret_key=os.getenv('ALPACA_SECRET_KEY')
)
try:
risk_mgr.check_position_limits("AAPL", 100, max_position_pct=10)
risk_mgr.check_buying_power("AAPL", 100)
print("Trade passes risk checks")
except ValueError as e:
print(f"Risk check failed: {e}")uvx alpaca-mcp-server --version~/Library/Logs/Claude/mcp*.log%APPDATA%\Claude\logs\Error: Invalid API credentialsALPACA_PAPER_TRADE=trueError: Tool 'xyz' not foundALPACA_TOOLSETSError: Rate limit exceededALPACA_PAPER_TRADEError: Cannot connect to Docker daemondocker images | grep alpacadocker logs <container_id>Error: Order rejected - insufficient buying power