Class BrokerToolFactory

java.lang.Object
com.eqixiac.equinix.mcp.server.broker.BrokerToolFactory

public final class BrokerToolFactory extends Object
The Safe Mutation Broker's two tools - fabric_propose_change and fabric_confirm_change - registered through the exact same ToolRegistration seam as the read-only catalog, in the opt-in Toolset.MUTATE toolset.

The two tools returned by one tools(...) call share one ProposalStore, so a token minted by that propose tool is confirmable only by its paired confirm tool - i.e. within one server instance. The store-taking overload is the test seam (deterministic clocks, pre-seeded proposals).

Human confirmation at confirm time

fabric_confirm_change asks the MCP client to show the change to a person before it executes (ServerContext.confirmWithHuman(String)). The order is fixed: consume the token, recompile the stored spec and compare the compiled request's SHA-256 with the one the token is bound to, prompt, re-check the TTL, execute. The prompt states the change type, the target, the price context the proposal reported, the proposal's age, the request SHA-256 and every field.

What the token is bound to

The propose phase compiles the spec into the exact create request (ChangeCompiler) and binds the token to the SHA-256 of that request: the change type and the canonical JSON body the HTTP layer serializes. The confirm phase compiles the stored spec again and executes only when the new request hashes to the bound value, so any drift between what the dry run validated and what would be sent (a different SDK mapping, a time-relative field, a tampered store) stops the create.

Cancellation

A client notifications/cancelled stops fabric_confirm_change at any point before the create request is sent: before the token is consumed (the token stays usable), during the human prompt (the prompt is abandoned) or after it. Once the create has been sent the call finishes and its result says it executed, with cancellation.requested_after_send = true when a cancel arrived too late.

Confirm outcomes by human-confirmation status
human_confirmation.statusExecutedToken afterwards
acceptedyesconsumed
declined, cancelled, timed_out, failedno consumed; a new proposal is required
unsupported_by_clientno, unless EQUINIX_MCP_ALLOW_UNCONFIRMED_MUTATIONS=trueconsumed

unsupported_by_client fails closed by default: a client that did not declare form elicitation cannot be prompted, so the server cannot verify a human approval and refuses to execute. An operator whose host shows its own per-tool approval can opt in with EQUINIX_MCP_ALLOW_UNCONFIRMED_MUTATIONS=true; the result then reports that no server-side check ran. The prompt is the broker's counterpart of the "Confused Deputy Resolution" requirement in the Connection Coordinator specification (connection-coordinator/docs/Protocols.md): evidence that the inciting action came from the customer. Beta: that section of the specification is marked work in progress, and the counterpart here is an analogy, not an implementation of it.

Vocabulary

The chg- confirm token is a process-local lookup key. It is not an activation key: activation keys are issued by cloud providers for native multicloud links and are entered at the other provider. Tool text never calls the token an activation key, so a model has no reason to put one where the other belongs.

Annotation honesty: both tools carry readOnlyHint=false because the pair exists to mutate - but the propose phase itself provisions nothing (its API call is the spec-documented dryRun=true validation), and destructiveHint is explicitly false on both: every change type is a purely additive create, and no delete or update tools exist.

  • Method Details

    • tools

      public static List<ToolRegistration> tools()
      Builds the broker tool pair over a fresh ProposalStore (10-minute single-use tokens). Called once per server build, so each server instance gets its own store.
      Returns:
      the propose/confirm registrations, sharing one store
    • tools

      public static List<ToolRegistration> tools(ProposalStore store)
      Builds the broker tool pair over the given store - the seam tests use for deterministic clocks and pre-seeded proposals.
      Parameters:
      store - the proposal store both tools share
      Returns:
      the propose/confirm registrations