alpacahq / alpacahq/alpaca-mcp-server

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

未关闭
#97 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看
主要语言
Python
星标
961
派生
311
平均合并
2 天 13 小时
30 天内合并 PR
4

描述

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

贡献指南

这个仓库没有索引到贡献指南

调研方向

Start at src/alpaca_mcp_server/overrides.py and the place_option_order entry point, then inspect how its parameter schema and docstring are surfaced to the MCP client. Reproduce the reported mleg request with the legs array, confirm the schema preserves it as a list, and update the time_in_force documentation; verify that the MCP call accepts the multi-leg payload and the docstring no longer claims day is the only option.

由索引模型根据 Issue 内容生成。

评估

技术栈
python
领域
api
Issue 类型
缺陷
难度
3/5
预计耗时
1-2 天
活跃度
冷清
描述清晰度
基本清楚
新手友好度
55/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。