MCP
How a session works
Find, open, snapshot, propose, apply: the life of an edit through the MCP server.
The Keystone MCP server lets an assistant change a business's information without ever being able to change it alone. Every write passes through a human click on a card. This page walks the sequence; the tool reference has each tool's schema.
The sequence
- Find. The model calls
find_businesswith a name, website, or domain. The server lists matches and shows a picker card. Each match is editable (the user holds a claim on it and its site is not live) or locked with a reason. - Open. The user clicks a business on the card. The card calls
open_sessionwith a card token minted for that exact click; the server opens an edit session on the Edits API and returns thesession_idto the model. The model cannot do this step. - Read. The model calls
get_snapshotwith the session id: the profile and every record with its id, label, andversion.read_businessreturns one record in full with its write field names. - Propose. The model calls
propose_changeswith up to 50 change items, each carrying theexpectedvalues orversionit read. The server stages a changeset; nothing is saved. The card shows each change, ticked, naming the business. - Apply. The user unticks what they do not want and clicks Apply. The card calls
apply_changesetwith its token; SOR applies each item with compare-and-swap and writes it to Change History. - Undo, if needed. The card offers Undo;
undo_changesetreverts the applied items. A value changed again since the apply is kept.
Claims
A business can be edited only while the user holds a claim on it (24 hours, extendable) and its website is not live. A business nobody holds, and that has not launched, shows Claim on the picker; claim_business takes it. Live businesses are edited in the console, where Change History and Undo work the same way.
Sessions expire
A session has an expiry returned by open_session. After it, get_snapshot and propose_changes fail with a reason; find and open again.
Refusals
Anything SOR refuses (not claimed, launched, conflict, validation) comes back as the tool's text result with the code, and for a changeset, each refused item by position. The model is expected to fix and resend only those.