One Robinhood login reaches several accounts, and every account-scoped tool takes account_number. Nothing sent one, and every consumer read the reply one level too shallow (data.positions where Robinhood nests data.data.positions), so the portfolio could not use Robinhood and the live runner and pre-trade gate failed closed on every read. Shapes: one module, connectors/robinhood/mcp.py, reads every Robinhood reply, built only from the shapes posted on #1428 (observed get_accounts and get_portfolio, advertised get_equity_positions outputSchema). A non-empty data.next, a null list or item, or an unmapped data key is an error, never a shorter account. Portfolio (#1428): robinhood-live-mcp-readonly shares the MCP server and OAuth grant. A connection instance carries account_ref, chosen from get_accounts through the API, the CLI (connector select-account, setup --account) or the connection center, with nothing preselected. A source with no account errors before any call. Positions stay unpriced, because the profile declares no quotes.read. A non-zero or unreported options, crypto, futures, event-contract, mutual-fund or fixed-income value fails the source. Live (#1442): /mandate/commit requires an account for such a broker and checks it against get_accounts (listed, not deactivated, agentic_allowed). The Web confirm dialog and the CLI REPL ask the user to pick from GET /live/accounts, and never take the account from the agent-written proposal. Runner reads and submits, the ceiling fetch and the gate's reads resolve the mandate's account on each call and unwrap through the same module. The gate refuses an unbound mandate or an order naming another account, and prices held positions through the order-notional quote path, failing closed per row. Existing gate and runner tests encoded replies Robinhood never sends. They now use tests/robinhood_mcp_helpers.py.
This commit is contained in:
1 parent
0de55cdd20
commit
1b888f8c3f
46 files changed
+2856
-114
No files matched your search
@@ -5,6 +5,21 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
- **A Robinhood account can be a read-only portfolio source** (#1428). The new
|
||||
`robinhood-live-mcp-readonly` profile uses the same MCP server and OAuth
|
||||
grant as the trading profile. Its connection reads exactly one account,
|
||||
picked from Robinhood's own `get_accounts` list in the connection center or
|
||||
with `vibe-trading connector select-account <id>`. Nothing is preselected,
|
||||
and a source with no account errors before any broker call. Holdings come
|
||||
from `get_portfolio` and `get_equity_positions` and are mapped only from the
|
||||
shapes the reporter posted. A second page of positions, a null list or item,
|
||||
or an unknown field is an error, not a shorter account. Positions show
|
||||
quantity and cost but no price until the quote reply is mapped. An account
|
||||
that also holds options, crypto, futures, event contracts, mutual funds or
|
||||
fixed income fails the source instead of showing an equity-only view.
|
||||
|
||||
### Changed
|
||||
|
||||
- **The final-answer grounding gate no longer guesses what a number is from the
|
||||
@@ -61,6 +76,22 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
||||
|
||||
### Fixed
|
||||
|
||||
- **Robinhood live trading reads and trades the account the mandate names**
|
||||
(#1442). The runner, the pre-trade gate and the commit-time ceiling fetch
|
||||
called Robinhood with no `account_number`, and read replies one level too
|
||||
shallow (`data.positions` where Robinhood nests `data.data.positions`). So
|
||||
every reconciliation aborted, and the gate refused every order because it
|
||||
could not read positions. The tests stayed green only because their fake
|
||||
replies had a shape Robinhood never sends. A Robinhood mandate is now bound
|
||||
at commit to one account from `get_accounts`: listed, not deactivated, and
|
||||
open to agentic trading. The Web confirm dialog and the CLI both ask for
|
||||
it, and never take it from the agent-written proposal. Every runner and gate
|
||||
call sends that account, and an order naming another account is refused.
|
||||
Held positions, which Robinhood reports without a price, are priced the way
|
||||
a quantity order already was, and one that cannot be priced fails the
|
||||
exposure check closed. Existing Robinhood mandates must be committed again
|
||||
with an account.
|
||||
|
||||
- **Plain integers in prose are not price claims.** A list number ("输出原则
|
||||
4"), a window length or a count was checked like a quoted price and could be
|
||||
cut from a released answer.
|
||||
|
||||
Reference in new issue
Block a user