Intelligence

The Mandate Capped the Trade at $750. The MCP Gate Approved an Order the Broker Could Fill for $1,000.

Vibe-Trading's MCP gate for live broker orders priced a buy limit order at the market quote alone, so a mandate capping order notional at $750 allowed and forwarded an order the broker could fill for $1,000. The direct SDK trading path had already been fixed for the identical gap five days earlier.

Event analysed: . This analysis was published on 7 September 2026.

When Vibe-Trading's MCP gate for live broker orders checked a buy limit order against a mandate's notional cap, did it check the order's largest possible executable cost, or only its cost at the current market quote?

Only the current quote, until 6 September 2026, and the gap let an order pass a smaller cap than its own terms permitted. Vibe-Trading, an open source LLM agent trading framework maintained by HKUDS, enforces a per order notional ceiling, max_order_notional_usd, before a live order reaches a connected broker. Two independently maintained gates do that enforcement: a direct SDK gate, and an MCP gate, LiveOrderGuardTool, wrapping a broker's own MCP order placing tool. Before pull request 1312, merged 1 September 2026, the direct SDK gate priced a buy limit order's notional from the live quote alone. Because a buy limit is fillable at any price up to its own limit, a limit above the quote let the broker fill for more than the gate had checked. Pull request 1312 fixed the SDK gate by pricing a buy limit at the larger of the live quote and the submitted limit price. Pull request 1361, merged 6 September 2026, fixed the identical gap on the MCP gate, five days later. Until then, the Robinhood connector's own extractor never mapped a submitted limit_price into the order intent the MCP gate reasons over, and the MCP gate's own notional arithmetic used the live quote alone, even though the order forwarded to the broker still carried its full limit price. A mandate capping max_order_notional_usd at $750, a live quote of $100, and a submitted order of 5 units at a $200 buy limit produced an allowed, forwarded order priced by the gate at $500, 5 units times the $100 quote, while the order's own terms permitted a broker fill of up to $1,000, 33 percent above the mandate. This record does not claim a real $1,000 fill occurred. The verified fact is that the gate allowed and forwarded an order whose own submitted terms permitted one. Both pull requests describe their fix in near identical language, and pull request 1361's own merge commit message states plainly that the MCP gate carried dead plumbing: the shared object the gate reads, OrderIntent, already had a field for the limit price after pull request 1312, but nothing on the MCP path used it until this second fix, five days later.

A quantitative mandate is supposed to mean the same thing wherever it is checked. Vibe-Trading's own live trading channel enforces one, a per order notional ceiling called max_order_notional_usd, through two separate gates guarding two separate ways an agent can place a real order: a direct SDK call, and a broker's own tool reached through the Model Context Protocol. For five days in September 2026, those two gates enforced the ceiling differently, and the surface that lagged did not merely check the same thing more loosely. It checked a smaller number than the order in front of it could actually cost.

What pull request 1361 actually fixed

Pull request 1361, titled fix live size MCP buy limit orders at the worse of quote and limit, was opened 5 September 2026 and merged 6 September 2026 as merge commit 07ad49f888c7ef658c773eeba4eb0a278d3bc8ea. It fixes Vibe-Trading's MCP order placing gate, LiveOrderGuardTool in src.live.order_guard, together with the Robinhood connector's own order intent extractor. Independently cloning the public HKUDS/vibe-trading repository and reading both the merge commit and its parent directly, rather than relying on the pull request's own rendered description, confirms the mechanism precisely. Before the fix, LiveOrderGuardTool._normalize_intent_notional derived a quantity order's enforced notional by multiplying the requested quantity by a single price, drawn from the broker's own live quote. A field named limit_price already existed on the shared OrderIntent object every gate reads, added five days earlier by a related pull request on Vibe-Trading's direct SDK trading path, but nothing on the MCP path populated or consulted it. The fix adds two changes in the same commit: the Robinhood extractor now maps a submitted limit_price keyword argument into the normalized OrderIntent, denying the order outright when that value is present but unparseable, non positive, or non finite, rather than guessing; and order_guard now prices a buy limit order at the larger of the live quote and that limit price, leaving a sell limit priced at the quote alone, since a sell limit does not create additional exposure the way a buy limit does.

Independently verified for this record, not accepted from the pull request's own text: the repository was cloned directly, both the pre fix commit and the fixed commit were checked out, and the pull request's own added test files were run against each. At the pre fix commit, 8 of 29 relevant assertions fail. At the fixed commit, all 29 pass. One of the failing assertions at the pre fix commit is the exact scenario this record leads with: quantity 5, live quote $100, buy limit $200, mandate $750, which returns an allowed, forwarded order at the pre fix commit and a blocked one at the fixed commit.

Two omissions, not one, on the same surface

The MCP path's own defect is worth separating into its two parts, because each is independently instructive. The first is a representation gap: extract_order_intent, the function that turns a broker's own MCP tool call arguments into the object the gate reasons over, simply never read a limit_price keyword argument, so the normalized intent the mandate check evaluated never carried one, no matter what the agent had actually submitted. The second is an arithmetic gap, present even where the first is fixed: the direct SDK gate's own pre fix formula, sdk_order_gate._implied_notional, also priced every quantity order from the live quote alone, with no comparison against a limit price, even on a version of OrderIntent that already carried the field. Pull request 1312 closed the second gap on the SDK path five days before pull request 1361 closed both gaps on the MCP path.

The two gaps compound in a specific way worth stating plainly. Vibe-Trading's own MCP tool wrapper forwards to the broker every keyword argument its schema allows, independent of what the gate's own normalized intent carries. That means a submitted limit_price reached Robinhood's own place_equity_order call unchanged throughout, even while the pre fix extractor dropped it from the object the authorization decision was computed against. The order that would have executed, if forwarded, and the order the mandate check believed it was authorizing, were never the same object.

The reproduction, verified directly

Pull request 1361 adds a reproduction of the exact scenario this record leads with, and this record re ran it independently rather than accepting the pull request's own claim. A mandate is written setting max_order_notional_usd to $750. A connected broker's live quote for a symbol is $100. An agent submits a buy order for 5 units at a $200 limit. At the pre fix commit, LiveOrderGuardTool's own notional check prices the order at 5 units times the $100 quote, $500, finds that inside the $750 mandate, and returns an allowed decision that forwards the full order, limit price included, to the broker. At the fixed commit, the identical call is priced at the larger of the $100 quote and the $200 limit, $1,000, found to exceed the $750 mandate, and blocked before any broker call is made.

What this record does and does not claim. The broker's own execution semantics permit a limit order to fill anywhere up to its stated limit, so the order's own submitted terms permitted a fill of up to $1,000, 33 percent above the mandate. This record does not claim a real $1,000 fill occurred against a funded account; the reproduction runs against the repository's own test fixtures and mandate mock, not a live broker. The verified fact, independently confirmed against both commits directly, is narrower and does not need a real fill to matter: the authorization gate allowed and forwarded an order whose executable terms exceeded the mandate it was supposed to enforce.

Five days between two fixes for the identical gap

Pull request 1312, titled fix live size buy limit orders at the worse of quote and limit, was merged 1 September 2026 as commit 789ca2b11255f2abe2c54f83c838e34a123a7702, independently confirmed by cloning the repository and reading that commit and its parent directly. It fixed the direct SDK gate, adding limit_price to the shared OrderIntent object and pricing a buy limit at the larger of the quote and the limit inside sdk_order_gate._implied_notional. Pull request 1361's own merge commit message is direct about the relationship between the two: it describes the MCP path, after pull request 1312 landed, as carrying dead plumbing, an OrderIntent field the object already had and nothing on the MCP path read or wrote. For five days, the identical mandate, applied to the identical action, a buy limit order against a connected broker, was enforced correctly on one execution surface and not on the other. Nothing in the repository's own test suite, before pull request 1361, asserted that the two surfaces agreed.

What remains unestablished

Several things this record does not extend beyond what the evidence supports. Vibe-Trading's MCP gate registers only one broker, Robinhood, in its own extractor lookup table as of the fixed commit; whether an equivalent gap exists, or ever existed, for any other broker's MCP tool is not established here, because no other broker's MCP order placing tool is currently gated at all. Robinhood's own place_equity_order tool, as mapped by this extractor, carries no stop price or comparable trigger field, so this record does not generalize the worse of rule to stop orders or other order types without evidence a concrete broker schema exposes one. Nothing available to this record states that either fix followed a live production incident rather than the maintainers' own review; the commit messages describe a sizing hole closed on each surface in turn, not an exploited one. And the direct SDK gate's own fix, verified here to have merged 1 September 2026, is not evidence that every quantitative check on that surface is now complete, only that this specific sizing rule was corrected there first.

The Authority Provenance ledger

Principal and mandate. Whoever configured the connected Robinhood account's mandate, setting max_order_notional_usd and the account's other hard caps through Vibe-Trading's own mandate store. Unnamed in the pull requests themselves; this record treats the principal as whoever holds that mandate file, consistent with how Vibe-Trading's own live trading channel is documented to work.

Submitted action. A buy order for a connected broker's equity symbol, carrying a quantity and, for a limit order, a limit price, submitted either through Vibe-Trading's direct SDK trading path or through the broker's own MCP tool, gated by LiveOrderGuardTool.

Execution bound parameter. The order's own limit price, which the broker's own execution semantics permit filling at any point up to, distinct from the live quote observed at the moment the order was authorized.

Normalized authorization object. OrderIntent, the object both gates reason over. After pull request 1312, it carried a limit_price field; before pull request 1361, the MCP path's own extractor never populated that field from a Robinhood order's own kwargs, so the field reached the SDK gate's evaluation but not the MCP gate's.

Forwarded execution object. The raw keyword arguments Vibe-Trading's MCP tool wrapper forwards to Robinhood's own place_equity_order call, filtered only against the broker's declared schema, independent of what the normalized OrderIntent carried. This object always carried the full submitted limit price, on both sides of the fix.

Maximum executable effect. The order's quantity times the larger of the live quote and the submitted limit price, for a buy order; the quantity times the live quote alone, for a sell order, since a sell limit does not create additional exposure.

Decision. Automated, both before and after the fix: LiveOrderGuardTool's own notional check against the mandate's max_order_notional_usd, with no human approval step in the gate path itself. What changed on 6 September 2026 was the value that decision was computed from, not whether a human was in the loop.

Where this sits against what Moona Intelligence has already written

Robinhood's own Agentic Trading opened a dedicated, capital isolated account for a connected agent to trade inside, with previews and a spending cap the customer set. This record concerns a different party's own trading infrastructure, an open source agent framework connecting to that same kind of brokerage account, and a narrower, more mechanical failure: not whether a cap existed, but whether the cap's own arithmetic used the right basis value once a limit order was in play.

Your Bourse's MCP connection to Trade Server raised an unresolved question about where a confirmation step is actually enforced, the server or the connecting client. Vibe-Trading's own gate is enforced server side, inside the agent's own process, on both surfaces; what failed here was not where the check ran but what number it ran on.

ZenHive's mpp showed a payment sponsor's own budget check passing honestly while a separate, unrelated field with its own persistent authority consequence rode along inside the same signed object, unexamined. Vibe-Trading's own gap is a close cousin, not the same mechanism: the parameter in question, the limit price, bears on the identical quantity the ceiling is trying to bound, the order's own cost, rather than on an unrelated effect the ceiling was never written to check at all. The lesson generalizes the same underlying principle, that a quantitative authorization decision has to be evaluated against the complete submitted action, from two different concrete shapes of failure five days apart on two different systems.

Sources

This analysis interprets third-party reporting, research and announcements. Moona is not the original reporter of the underlying events.

[1]
fix(live): size MCP buy-limit orders at the worse of quote and limit (pull request 1361)
GitHub, HKUDS/Vibe-Trading · 6 September 2026 · Primary source
[2]
fix(live): size buy-limit orders at the worse of quote and limit (pull request 1312)
GitHub, HKUDS/Vibe-Trading · 1 September 2026 · Primary source
[3]
HKUDS/vibe-trading, commit 07ad49f888c7ef658c773eeba4eb0a278d3bc8ea (merge of pull request 1361)
GitHub, HKUDS/Vibe-Trading · 6 September 2026 · Primary source
[4]
HKUDS/vibe-trading, commit 789ca2b11255f2abe2c54f83c838e34a123a7702 (merge of pull request 1312)
GitHub, HKUDS/Vibe-Trading · 1 September 2026 · Primary source
[6]
HKUDS/vibe-trading
GitHub · Primary source

Protocol evidence

This record does not assess these architectures. The connection runs through the Risk Registry requirement each one bears on, and these published authority architectures are what the evidence says about that requirement.

Protocol evidence related through AEW-034 Quantitative mandate sized from the observed value, not the maximum executable effect

  • Missing requirement

    Agent Action Decision Protocol (AADP)

    Shamik Saha, individual submission to the IETF

    Requirement Concurrent requests must not independently consume the same remaining budget

    AADP's own described atomic budget reservation answers a concurrency question: whether two simultaneous requests can each believe they consumed the same remaining unit of a budget. Vibe-Trading's own MCP gate defect is not a concurrency failure; a single order, evaluated once, was priced against the wrong basis value. Nothing in AADP's own described budget accounting, as corroborated here, states that a reserved amount must itself be derived from the maximum executable cost a submitted action's own parameters permit, as distinct from correctly reserving whatever amount a caller declares. Recorded as a requirement this dataset's evaluated protocols do not currently name, not as a defect in AADP's own atomic reservation mechanism, which answers a different, real question.

    This record is the cited evidence for this relationship.

    View protocol evidence

  • Missing requirement

    ChainIT Authority Protocol and Agent Subject Profile for pre execution authority validation

    ChainIT

    Requirement A canonical transaction digest is described binding payer, payee, destination, amount, currency or asset and payment rail to approval and execution

    ChainIT's own described canonical transaction digest binds a named amount field to both approval and execution, which is a real answer to a digest disagreeing with itself after the fact. It is not, on the material this dataset corroborates, an answer to whether the bound amount itself already reflects the largest value the action's own other submitted parameters could produce at execution. Vibe-Trading's own pre-fix MCP gate demonstrates exactly that gap outside any digest scheme: the notional the gate approved, 500 dollars, was faithfully the value its own arithmetic computed, and the binding between that approved value and the forwarded order was never in question. What was missing was a requirement that the approved value itself be derived from the order's maximum executable cost, 1,000 dollars once the submitted limit price is accounted for, rather than from the live quote alone. Recorded as a requirement this dataset's evaluated protocols do not currently name, not as a defect in ChainIT's own digest binding, which this record does not treat as deployed here.

    This record is the cited evidence for this relationship.

    View protocol evidence

Protocol evidence related through AEW-035 Equivalent actions resolve to different authority decisions across execution surfaces

  • Missing requirement

    Agent Control Standard (ACS)

    OWASP GenAI Security Project, originally Zenity

    Requirement The specification does not guarantee complete mediation of every consequential action a host can take

    ACS's own stated conformance position, that a MUST level mediation requirement binds a host framework's own compliance rather than an independent enforcement mechanism, and that a permissive Guardian is a conformant but permissive deployment rather than a violation, already anticipates that mediation completeness is not guaranteed by the specification alone. Vibe-Trading's own two gates are a concrete instance of exactly that gap, one layer more specific than ACS's own framing: the same specification, or in this case the same intended mandate, was implemented as two independently maintained gates for two execution surfaces, the direct SDK path and the MCP path, and a fix to one carried no guarantee, and in fact no effect at all, on the other for five days. ACS's own conformance language does not go further and state that equivalent actions across a host's own multiple execution surfaces must be evaluated by one shared rule rather than parallel, independently maintained ones. Recorded as a requirement this dataset's evaluated protocols do not currently name, not as a defect in ACS's own stated, narrower conformance bar.

    This record is the cited evidence for this relationship.

    View protocol evidence

Related Intelligence

All Intelligence Records →