Package com.eqixiac.equinix.mcp.server.broker
The broker is a two-phase protocol over two tools in the opt-in mutate toolset
(never served unless the operator names it in the toolset selection):
fabric_propose_change- takes a typed create specification (ChangeType: connection, network, or service-token create; there are no update or delete change types) and executes the real, spec-documented dry run through the SDK's fluent creators (dryRun=trueon the actual Fabric v4 endpoint). The Equinix API validates the exact payload that a confirm would send, but provisions nothing. The tool returns the validated entity, a rate-card price context where estimable (honestunpricedotherwise), the compiled request, and a single-use confirm token bound to the SHA-256 of that compiled request (the change type plus the canonical JSON body sent on the wire).fabric_confirm_change- takes only the confirm token, recompiles the stored spec and requires it to produce the bound request, asks the MCP client to obtain the user's approval, re-checks the TTL when the answer arrives, and on approval sends that request withoutdryRun, creating billable resources. The agent cannot alter the spec between phases: a different spec is a different proposal with a different token, and any drift between what the dry run validated and what would be sent stops the create.
Tokens live in the in-memory, single-process
ProposalStore for 10 minutes and are consumed
on the first confirm attempt, successful or not. At most 20 proposals are pending; proposing
beyond that evicts the oldest and the propose result lists it under evicted_proposals.
Expired, evicted, unknown and replayed tokens each fail with a message telling the agent to
re-propose. Every confirm result and every token error carries the redemption predicates as
confirm_checks: proposal_exists, not_evicted, not_expired,
not_previously_used, request_matches_binding.
A client notifications/cancelled stops fabric_confirm_change before the
create is sent (the token is not consumed when the call is cancelled before it starts); once the
create has been sent the result reports that it executed.
Human confirmation
A tool argument cannot prove a person approved a mutation, because the calling model writes
every argument. The MCP client can: it is the party that renders an elicitation to the user.
fabric_confirm_change therefore sends a form elicitation (change type, target, price
context, proposal age, request SHA-256 and every field of the compiled request) after consuming
the token and before executing.
| Client | Answer | human_confirmation.status | Executed |
|---|---|---|---|
| declared form elicitation | accept with confirm = true |
accepted | yes |
| declared form elicitation | decline, or accept without confirm = true |
declined | no |
| declared form elicitation | cancel | cancelled | no |
| declared form elicitation | none within EQUINIX_MCP_ELICIT_TIMEOUT_MS
(default 300000 ms) | timed_out | no |
| declared form elicitation | the round trip failed | failed | no |
| declared form elicitation | the client cancelled the tool call | call_cancelled | no |
| declared form elicitation | accept, but after the proposal's TTL | accepted (not_expired = false) | no |
| did not declare it | not asked | unsupported_by_client |
no, unless the operator set EQUINIX_MCP_ALLOW_UNCONFIRMED_MUTATIONS=true |
The token stays consumed in every row. Limits: an accepted status proves the client
reported an acceptance, not that a person read the prompt; and with the opt-in above, a client
without elicitation support gets no server-side check at all. Beta: the prompt is modelled on the "Confused
Deputy Resolution" requirement of the Connection Coordinator specification
(connection-coordinator/docs/Protocols.md, marked work in progress there) and is an
analogy to it, not an implementation of it.
Vocabulary
The chg- confirm token is a lookup key into one process's proposal store. It is not an
activation key. Activation keys are issued by a cloud provider when a customer creates a native
multicloud link and are entered at the other provider; the broker neither mints nor accepts
them.
Policy, matching the read-only catalog's rules: no delete tools of any kind, and no mutation outside this broker.
-
ClassDescriptionThe Safe Mutation Broker's two tools -
fabric_propose_changeandfabric_confirm_change- registered through the exact sameToolRegistrationseam as the read-only catalog, in the opt-inToolset.MUTATEtoolset.The mutations the Safe Mutation Broker can carry - deliberately the smallest honest set: three creates, each backed by a spec-documented Fabric v4 dry run the propose phase exercises for real.One dry-run-validated proposal awaiting confirmation: the single-use confirm token, the change type, the exact canonicalized spec the dry run validated (the confirm phase recompiles this stored spec - never a re-supplied one), the SHA-256 of the compiled request the token is bound to, the mint and expiry instants, and the price context the proposal reported.In-memory, TTL-bounded, single-use store for the Safe Mutation Broker's pending proposals, keyed by confirm token.The result of one consume attempt.How aProposalStore.consume(String)attempt resolved.