alpacahq / alpacahq/alpaca-mcp-server
Multi-leg place_option_order rejects legs as string instead of array; time_in_force docstring inaccurate.
- Vorherrschende Sprache
- Python
- Sterne
- 959
- Forks
- 311
- Ø Merge
- 2 T. 13 Std.
- Gemergte PRs (30 T.)
- 4
Beschreibung
Bug: legs parameter on place_option_order rejected as string, not array
Repo: alpacahq/alpaca-mcp-server
Component: src/alpaca_mcp_server/overrides.py → place_option_order
Client: Claude Desktop / Cowork (MCP tool-calling bridge), uvx alpaca-mcp-server, paper trading account
Summary
Calling place_option_order with order_class="mleg" and a legs array fails with a pydantic validation error indicating the array arrived as a raw JSON string rather than a parsed list. This blocks all multi-leg (spread, iron condor, etc.) order placement through this tool when called via Claude Desktop/Cowork's MCP client. Single-leg orders on the same tool work fine.
Reproduction
Call place_option_order with:
json{
"qty": "1",
"order_class": "mleg",
"type": "limit",
"limit_price": "-0.01",
"time_in_force": "gtc",
"legs": [
{"symbol": "SPY260731P00395000", "ratio_qty": "1", "side": "sell", "position_intent": "sell_to_open"},
{"symbol": "SPY260731P00380000", "ratio_qty": "1", "side": "buy", "position_intent": "buy_to_open"}
]
}
Result:
1 validation error for call[place_option_order]
legs
Input should be a valid list [type=list_type, input_value='[{"symbol":"SPY260731P00...intent":"buy_to_open"}]', input_type=str]
Tried multiple encodings of the legs value (inline JSON, pretty-printed, trailing newline) — same failure every time, both before and after a full reconnect/restart of the MCP connection with fresh credentials. Ruled out an auth/staleness cause.
Source inspection
Confirmed in overrides.py that the parameter is correctly typed in Python:
pythonlegs: Optional[list[dict]] = None
This looks correct on the server side — the issue appears to be in how this parameter's schema is surfaced to / interpreted by the MCP client during tool invocation, not in the tool's Python signature itself.
Workaround (confirms the API and server code are both fine)
Bypassing the MCP tool entirely and POSTing the identical payload directly to https://paper-api.alpaca.markets/v2/orders via a plain requests call succeeds:
Status Code: 200
"order_class":"mleg", "time_in_force":"gtc", "status":"pending_new", legs correctly populated with both sides
This confirms Alpaca's REST API and overrides.py's handling are both correct — the break is specifically in the array parameter transmission between the declared tool schema and the MCP client invocation.
Secondary issue (docs-only, same tool)
The time_in_force docstring for place_option_order reads:
time_in_force: "day" only. Options do not support other values.
This is inaccurate. The code applies no such restriction (it passes time_in_force straight through), and Alpaca's API accepts "gtc" for options — confirmed by placing and filling/canceling a real single-leg GTC order through this exact tool (time_in_force: "gtc", status: "pending_new", accepted without error). Worth correcting the docstring so LLM callers don't avoid GTC unnecessarily.
Environment
alpaca-mcp-server via uvx alpaca-mcp-server (latest at time of testing, July 2026)
Claude Desktop config: "command": "uvx", "args": ["alpaca-mcp-server"]
Paper trading account, options level 3
Beitragsleitfaden
Für dieses Repository ist kein Beitragsleitfaden indexiert
Bewertung
Dieses Issue wurde noch nicht bewertet.