alpacahq / alpacahq/alpaca-mcp-server

Multi-leg place_option_order rejects legs as string instead of array; time_in_force docstring inaccurate.

Offen
#97 0 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen
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.

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.