Alpaca Finance API MCP Server Guide
Connect Alpaca Finance API to Model Context Protocol: Stream real-time market data, execute paper trades safely, and enforce autonomous budget guardrails.
Generate & Validate Multi-Client MCP Config
One-click export with environment variables & path locators for Claude Desktop, Cursor, Windsurf, and OpenAI Codex CLI.
Alpaca Finance API MCP Server Guide
Connecting real-time financial market data and trading APIs to the Model Context Protocol (MCP) allows engineering teams to construct intelligent financial research assistants, automated portfolio monitors, and quantitative strategy backtesters. Rather than switching between web portals and custom terminal scripts, developers can prompt AI agents in Claude Desktop, Cursor, or OpenAI Codex CLI to query real-time stock quotes, evaluate historical price action, and execute simulated paper trades.
However, financial execution environments introduce severe operational risks. If an autonomous agent enters an unconstrained retry loop or misinterprets an order volume parameter, it can rapidly deplete available capital. Operating a financial MCP server in production requires strict paper trading boundaries, hard budget caps, and multi-factor confirmation gates.
This guide provides an architectural blueprint, multi-client configuration blocks, a production TypeScript MCP implementation, and risk controls for integrating Alpaca Finance with the Model Context Protocol.
1. Architecture and Operational Safety Boundaries
An Alpaca MCP server functions as an isolated execution bridge between the reasoning LLM host and Alpaca brokerage infrastructure. The server enforces safety invariants before any order reaches Alpaca REST or WebSocket endpoints.
Safety Principles for Financial MCP Servers
- ▸Strict Paper Trading Isolation: Development and agent testing must exclusively target the Alpaca Paper Trading environment (
https://paper-api.alpaca.markets). Never configure production live trading keys in interactive AI agent settings. - ▸Hard Dollar Ceilings: Enforce maximum order size limits directly inside the MCP server tool logic. If an agent attempts to submit an order exceeding your preset safety threshold (such as $500), the server immediately rejects the request prior to network transmission.
- ▸Structured Quote Truncation: Financial data feeds emit voluminous historical bar arrays. The MCP server aggregates and filters tick records into token-efficient summaries to protect the agent context window.
2. Environment Prerequisites and Credentials Matrix
To deploy the Alpaca MCP server, verify your system meets the required environment dependencies:
| Component | Minimum Version | Description |
|---|---|---|
| Node.js | >= 20.0.0 | JavaScript runtime environment |
| npm | >= 10.0.0 | Package manager |
| @alpacahq/alpaca-trade-api | >= 3.1.0 | Official Alpaca Node.js REST and WebSocket client |
| @modelcontextprotocol/sdk | >= 1.2.0 | Core Model Context Protocol TypeScript framework |
Obtain your paper trading API credentials from the Alpaca Developer Portal (opens in a new tab). Set the required environment variables:
export APCA_API_KEY_ID="PKYOURPAPERKEYID"
export APCA_API_SECRET_KEY="your-paper-secret-key"
export APCA_PAPER="true"
export MAX_ORDER_DOLLAR_LIMIT="500"3. Multi-Host Configuration Snippets
Configure your MCP hosts to launch the Alpaca server over standard input and output (stdio). Ensure paper trading flags are explicitly asserted in each client definition.
Claude Desktop Configuration
Add the server definition to claude_desktop_config.json:
{
"mcpServers": {
"alpaca-finance": {
"command": "node",
"args": ["/opt/mcp-servers/alpaca/dist/index.js"],
"env": {
"APCA_API_KEY_ID": "PKYOURPAPERKEYID",
"APCA_API_SECRET_KEY": "your-paper-secret-key",
"APCA_PAPER": "true",
"MAX_ORDER_DOLLAR_LIMIT": "500"
}
}
}
}Cursor IDE Configuration
Place this definition inside .cursor/mcp.json:
{
"mcpServers": {
"alpaca-finance": {
"command": "node",
"args": ["./dist/index.js"],
"env": {
"APCA_API_KEY_ID": "PKYOURPAPERKEYID",
"APCA_API_SECRET_KEY": "your-paper-secret-key",
"APCA_PAPER": "true"
}
}
}
}OpenAI Codex CLI Configuration
In ~/.codex/config.toml, configure the server entry:
[mcp_servers.alpaca_finance]
command = "node"
args = ["/opt/mcp-servers/alpaca/dist/index.js"]
[mcp_servers.alpaca_finance.env]
APCA_API_KEY_ID = "PKYOURPAPERKEYID"
APCA_API_SECRET_KEY = "your-paper-secret-key"
APCA_PAPER = "true"4. Production TypeScript MCP Server Implementation
The following implementation provides three essential financial tools: get_stock_quote, get_account_balance, and a strictly guarded place_paper_order tool. Save this as src/index.ts:
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
import Alpaca from '@alpacahq/alpaca-trade-api';
const isPaper = process.env.APCA_PAPER === 'true';
const maxOrderLimit = parseFloat(process.env.MAX_ORDER_DOLLAR_LIMIT || '500');
if (!isPaper) {
process.stderr.write("FATAL ERROR: Alpaca MCP Server must run with APCA_PAPER='true'\n");
process.exit(1);
}
const alpaca = new Alpaca({
keyId: process.env.APCA_API_KEY_ID,
secretKey: process.env.APCA_API_SECRET_KEY,
paper: true
});
const server = new Server(
{ name: 'alpaca-finance-mcp', version: '1.0.0' },
{ capabilities: { tools: {} } }
);
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: 'get_stock_quote',
description: 'Fetch latest bid, ask, and last trade price for a US equity ticker.',
inputSchema: {
type: 'object',
properties: {
symbol: { type: 'string', description: 'Stock ticker symbol (e.g. AAPL, MSFT)' }
},
required: ['symbol']
}
},
{
name: 'get_account_balance',
description: 'Retrieve current paper trading cash balance, buying power, and portfolio equity.',
inputSchema: {
type: 'object',
properties: {}
}
},
{
name: 'place_paper_order',
description: 'Submit a simulated paper equity order with strict dollar value limits.',
inputSchema: {
type: 'object',
properties: {
symbol: { type: 'string', description: 'Stock ticker symbol' },
qty: { type: 'number', description: 'Number of whole shares to purchase' },
side: { type: 'string', enum: ['buy', 'sell'], description: 'Order direction' },
order_type: { type: 'string', enum: ['market', 'limit'], default: 'market' },
limit_price: { type: 'number', description: 'Mandatory limit price if order_type is limit' }
},
required: ['symbol', 'qty', 'side']
}
}
]
};
});
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
try {
if (name === 'get_stock_quote') {
const symbol = (args?.symbol as string).toUpperCase();
const quote = await alpaca.getLatestQuote(symbol);
return {
content: [
{
type: 'text',
text: JSON.stringify({
symbol,
ask_price: quote.AskPrice,
ask_size: quote.AskSize,
bid_price: quote.BidPrice,
bid_size: quote.BidSize,
timestamp: quote.Timestamp
}, null, 2)
}
]
};
}
if (name === 'get_account_balance') {
const account = await alpaca.getAccount();
return {
content: [
{
type: 'text',
text: JSON.stringify({
status: account.status,
currency: account.currency,
buying_power: account.buying_power,
cash: account.cash,
portfolio_value: account.portfolio_value
}, null, 2)
}
]
};
}
if (name === 'place_paper_order') {
const symbol = (args?.symbol as string).toUpperCase();
const qty = Number(args?.qty);
const side = args?.side as 'buy' | 'sell';
const orderType = (args?.order_type as 'market' | 'limit') || 'market';
const quote = await alpaca.getLatestQuote(symbol);
const estimatedCost = qty * quote.AskPrice;
if (estimatedCost > maxOrderLimit) {
return {
isError: true,
content: [
{
type: 'text',
text: `Order rejected: Estimated cost (${estimatedCost.toFixed(2)}) exceeds maximum dollar limit (${maxOrderLimit.toFixed(2)}).`
}
]
};
}
const orderPayload: any = {
symbol,
qty,
side,
type: orderType,
time_in_force: 'day'
};
if (orderType === 'limit') {
if (!args?.limit_price) {
throw new Error('Limit orders require a limit_price argument.');
}
orderPayload.limit_price = Number(args.limit_price);
}
const order = await alpaca.createOrder(orderPayload);
return {
content: [
{
type: 'text',
text: JSON.stringify({
status: 'submitted',
order_id: order.id,
symbol: order.symbol,
qty: order.qty,
side: order.side,
type: order.type
}, null, 2)
}
]
};
}
throw new Error(`Tool ${name} is not recognized.`);
} catch (err: any) {
return {
isError: true,
content: [{ type: 'text', text: `Alpaca API Error: ${err.message}` }]
};
}
});
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
}
main().catch((err) => {
process.stderr.write(`Fatal error: ${err.message}\n`);
process.exit(1);
});5. JSON-RPC 2.0 Wire Payloads
Inspecting the underlying JSON-RPC protocol messages facilitates auditing and integration testing.
Tool Invocation Request (tools/call)
{
"jsonrpc": "2.0",
"id": "alpaca-quote-42",
"method": "tools/call",
"params": {
"name": "get_stock_quote",
"arguments": {
"symbol": "AAPL"
}
}
}Result Payload
{
"jsonrpc": "2.0",
"id": "alpaca-quote-42",
"result": {
"content": [
{
"type": "text",
"text": "{\n \"symbol\": \"AAPL\",\n \"ask_price\": 224.50,\n \"ask_size\": 100,\n \"bid_price\": 224.48,\n \"bid_size\": 200,\n \"timestamp\": \"2026-10-09T20:30:00Z\"\n}"
}
]
}
}6. Common Errors and Production Troubleshooting
When connecting agents to financial market feeds, handle these operational error states:
Error: 403 Forbidden: invalid key or paper/live mismatch
- ▸Root Cause: Attempting to query paper trading endpoints using live account keys, or vice versa. Alpaca paper keys start with the prefix
PKand are invalid on live endpoints (api.alpaca.markets). - ▸Resolution: Ensure both
APCA_PAPER="true"is set and your API key starts withPK.
Error: insufficient buying power
- ▸Root Cause: The paper account cash balance has been exhausted by earlier automated tests.
- ▸Resolution: Reset your paper portfolio balance directly from the Alpaca developer dashboard under Paper Account Settings.
Error: order rejected: outside market hours
- ▸Root Cause: Submitting market orders outside standard US trading sessions (9:30 AM to 4:00 PM Eastern Time).
- ▸Resolution: Configure
extended_hours: trueif your account supports pre-market/after-hours trading, or submit limit orders for execution at next market open.
7. External Citations and Security Guardrails
Financial agent integrations must adhere to rigorous security and compliance boundaries:
- ▸Credential Isolation: Store brokerage keys in operating system keychains or secrets managers. Never commit raw API secret strings to repository configs.
- ▸Audit Logging: Maintain an append-only audit trail of all agent tool invocations and resulting order IDs for regulatory compliance.
- ▸Official Standards and Repositories:
Weekly Protocol Diffs & Verified Drops
New server guides, benchmarks, and security audits. No spam. Unsubscribe anytime.
Zero marketing spam. 1-click unsubscribe anytime.
Build your full agent toolstack in the Visual Generator
Combine Alpaca Finance API with databases, search APIs, and memory graphs in a single configuration file.
Did this setup guide work with your AI host?
Help test this configuration across Claude, Cursor, and Codex CLI. Be the first to report:
Alpaca Finance API MCP Server Guide FAQ
What is the Alpaca Finance API MCP Server Guide?
Connect Alpaca Finance API to Model Context Protocol: Stream real-time market data, execute paper trades safely, and enforce autonomous budget guardrails.
How do I configure Alpaca Finance API MCP Server Guide in Claude Desktop or Cursor?
You can copy the configuration JSON from our guide or launch the interactive MCP Codex Config Generator at https://mcp-codex.com/generator to export valid configs in 1 click.
Can I use Alpaca Finance API MCP Server Guide with the OpenAI Codex CLI?
Yes, OpenAI Codex CLI supports Model Context Protocol. You can add it directly to ~/.codex/config.toml or pass arguments to codex mcp add.
Specializing in Model Context Protocol (MCP) integrations, autonomous AI agent orchestration, and distributed developer toolchains. Researches and benchmarks production MCP client-server architectures across OpenAI Codex, Claude, and Cursor.
Related Guides
HubSpot and Zendesk MCP Integration Guide
Connect HubSpot CRM contacts and Zendesk tickets to Model Context Protocol agents: Automated ticket triage, contact enrichment, and safe draft workflows.
APIsAccepting Stripe's Machine Payments Protocol (MPP) in Your MCP Server
Charge agents per tool call with MPP: an MCP tool that returns a payment link, an endpoint that answers 402 with a challenge, and Shared Payment Token verification.
APIsPaying for MCP Tools with Stripe's Machine Payments Protocol (MPP)
How an MCP client pays for a tool call with MPP: the HTTP 402 challenge, Shared Payment Tokens from a Link agent wallet, and the stablecoin alternative.