Koskamo

Versum Agent Assistant MCP

An MCP server that allows AI agents to discover local businesses, view their offerings and prices, check real-time availability, and place orders or book appointments via direct links to the merchants' systems.

Endpoint and access

No sign-in to connect and list tools. Individual tools may still need a vendor account, credentials, or permissions; check the documented prerequisites.

Versum Agent Assistant MCP logo, by sudzikcoinCommunity listingStreamable HTTPNo sign-inEndpoint checked 2026-11-02Published by sudzikcoin
MCP endpoint (Streamable HTTP)
https://versum.suverse.io/mcp
Vendor documentation

What its tools do

13 tools, grouped by the hints the server advertises. Hints are self-declared, not verified behavior.

13 of 13 have a description · 0 of 13 declare behavior hints · 10 of 13 with parameters document them all

Checks and signals

Each line is separate evidence, not a trust score.

  • Passed Endpoint answered the live check ·
  • Availability 1 of 1 checks passed in 30 days
  • Popularity 1 GitHub star

What you can do with it

  • Search for local businesses by trade or query
  • Check product availability and pricing
  • Place orders through merchant checkout pages
  • Book appointment slots via Square Appointments

Source and maintenance

Community listingRegistry 1.0.0
Last repository push
Maintenance checked

Protocol and capabilities

Server
versum-catalog 1.6.0
MCP protocol negotiated in check
2025-06-18
Tools
13 advertised
Resources
Not advertised
Resource templates
Not advertised
Prompts
Not advertised
Server-advertised capabilities
{
  "tools": {
    "listChanged": true
  }
}

Server-provided instructions

Untrusted server output shown for inspection. It is not Koskamo guidance and is excluded from knowledge search.

Versum: a free, read-only index of real local businesses in the United States, read from the businesses’ own public websites. Nothing here takes money, places an order or reserves anything: every answer is a price, a link and a telephone number, and the user acts on them. WHICH TOOL, IN THIS ORDER. The shelf hands over facts; you choose. · The user NAMED a business → find_business with `intent` (book / order / quote / info) and `needed_by`: the match carries a TASK CARD — the hours on that day, up to 5 items under `query`, the conditions and `next` (what you may promise, what is only a candidate, ONE action with its link or phone). Name matching only, never a substitute: an empty `found` with `nearby_in_same_niche` is the honest answer. · You know the TRADE → list_niches (with `niche` for its condition keys and how many cards confirm each) → list_cards with `intent` (10 task cards a page, ≤ 2 KB each). get_card only for the full menu. · `next.promise` is confirmed by what the business published; `next.candidate` is unknown — put it to the business, never to the user as a fact. A free table or slot is never confirmed by opening hours. · You do NOT know the trade → search_catalog (a match by meaning; check its results on the cards; for a known trade prefer list_cards). list_cards never ranks: plain businesses, then chains, then marketplaces; a trade that travels to the customer puts the ones whose published area covers the place first; then distance. `query` only picks which offering is SHOWN on each card. An empty answer always says why and carries `gap_logged: true`. TWO WORDS, AND THEN NOTHING PER TRADE. A bouquet, a haircut, a plate of pasta and a two-bedroom house move come back as the same row with a different `kind`. · An OFFERING is anything a business sells. `price` is always the LOWEST number it published and `price_type` says how to read it: `fixed` ($45), `from` ($45+), `range` (price…price_max), `per_unit` (with `unit`: hour, session, room, month…), `quote_only` (they quote it rather than publishing it — say so; it is not «free» and not «unknown»), or null (nothing published and nothing said). `price_note` is that sentence already written for you — prefer it to composing your own. 🔴 `price: null` WITH a `price_note` that begins «no usable price» means a number WAS published and we refused it: it was read out of a sentence about a discount or a tip, or it is an order of magnitude under that same business’s other prices of the same kind. Quote the reason, never the number. · An ACTION is one of exactly SIX things and there are no others, ever: `order` (an address that puts it in a basket), `book` (a time can be had), `request_quote` (a price comes back from a person), `reserve` (a table or a slot, nothing bought), `contact`, `check_delivery`. In the short answer they are `can` (the names) and `links` (one address each); `needs` lists the fields a form will ask for. Every action carries the business’s telephone as well, because a link that fails must leave something behind. EVERY LINK IS TAGGED `ref=versum`. Hand it over exactly as given — that tag is how a business sees who sent it a buyer, and it is the only thing Versum asks for. THE SHORT ANSWER IS THE DEFAULT. `search_catalog` returns, per business: the id, the name, the trade, the distance, the telephone, its 1–2 best offerings, `can`/`links`/`needs`, the date it was read and `owner_verified`. Call again with `detail:"full"` for the images, the sentence each price was read from, the variants, all four fulfilment modes with the published delivery areas, the opening hours and the per-field evidence — or call `get_card` for one business, which is always full. 🔴 `owner_verified` IS FALSE ON EVERY ROW TODAY. These businesses have never been asked and do not know Versum exists. Quote prices, times and deadlines as «their website says», never as a promise, and let the user confirm on the business’s own page. 🔴 THREE STATES, NEVER TWO. Every price, availability, way of getting it (delivery, pickup, on_site, at_customer) and action is CONFIRMED (the business published it), REFUTED (it denied it) or UNKNOWN (nobody said), each with its source and the date it was read. Refuted is left out of an answer; unknown is KEPT, ranked a little lower, and named on the card in one line: `unknown: "bringing it to the address is not published; availability not published for «…»"`. Read unknown as a question to put to the business, never as a no — most businesses publish two or three of these facts, not all of them. A thing for a special occasion you did not ask for, or an accessory of another kind, is shown lower with a `note`, never hidden: what you asked for orders the shelf, it does not censor it. THE OPEN LAYER. Beside the core, every card carries `properties`: the facts the business publishes that have no column — a capacity, a deposit, a duration, what is included — each as the page wrote it, with its quote, source and date in the full card. When several businesses of one trade publish the same fact it is ESTABLISHED for that trade and `get_card` lists it under `established_properties`; `search_catalog` then filters by it (`properties: [{key, min, max, equals, exists}]`) with the same three states: published and fitting = kept, published and not fitting = left out, not published = kept lower and named in `unknown`. An action whose page used another verb («rent», «charter», «check availability») is mapped onto the nearest of the six and says so: `nearest_known: true`, `observed` = the page’s word, `required_fields` from its form. A price the page wrote as a RATE («$350 for 4 hours», «$450/day», «from $120 per hour») is an offering with `price_type: "per_unit"` (or "from"), `unit` = the page’s own word and `quantity` = how many units the figure buys, with the line as its quote; the unit is whatever the trade uses, not a fixed list. A MARKETPLACE — one address, a shelf that names places far from it — is kept, ranked lower and marked `marketplace: true`; pass `only_local: true` to leave marketplaces out. 🔴 AN EMPTY ANSWER IS A REAL ANSWER. The question is matched by meaning as well as by words, in any language, so «funeral flowers» finds a shop selling «sympathy sprays» — and «wedding cake Miami» still comes back empty, because this index holds no bakery. `nothing_found.reason` says WHICH empty it is: `no_coverage` (nothing read near there — a gap), `nothing_matched` (businesses read there, none sells this), `all_refuted` (matches exist and every one has denied the way of getting it you asked for — ask without it). Do not retry with synonyms of your own: that is what the meaning search is. CONNECTED BUSINESSES (2026-11-01). A card with `live_data` has its items, prices and stock from the business’s own Shopify or Square, synced at `live_data.synced_at` — confirmed by the system, not a paid placement. An action with method `connected` is taken HERE: check_availability (stock now, free slots), place_order (a draft order / an order with a payment link — hand `checkout_url` to the user, the platform takes the money, Versum holds no card), book_slot (an appointment), order_status. Every other business is `not_connected` on those tools and keeps its page doors in `can[]`. Get the user’s explicit yes before an order or a booking: they are real. HOW TO DEAL WITH A BUSINESS (2026-11-02). Every card carries `reach`: `online_platform` (order/book/ reserve through a platform — its keys in `platforms`, transacting ones first), `own_cart` (its own site takes the order or booking), `form_only` (only its own form), `phone_only` (site read, only a phone), `no_site` (no website, or a social page instead), `not_read` (its site has not been read yet). WHAT IT COSTS AT AN ADDRESS (2026-11-02). For a shop on WooCommerce or Shopify, `quote_order` asks the shop’s own public cart: delivery to that address yes/no, the options with their prices, tax, total. Nothing is ordered and no buyer data is sent beyond the address. Call it before you tell a user «delivered: $X». To HIRE a person, an agent tool or a machine for money instead of finding a shop, that is a different door: /mcp/x402, tool `find_offers`.

Tools

13 advertised

list_niches — What the catalogue knows, and where
Advertised by the server during the last successful anonymous check.

The niches (trades) this catalogue has read, each with its key, its other names, its TAGS (Google’s own type words and the kinds of thing on its shelves — e.g. a restaurant niche tagged with the cuisines its businesses carry) and how many businesses and cards it holds. With `location`: only the niches that have cards inside the radius, plus `known_not_scanned_here` — niches the catalogue knows but has not read there (a honest «no» before you search). Use a key, a name or a tag as `niche` in list_cards. `conditions`: the keys of the deal (a deposit, walk-ins, emergency service, new patients…) with how many cards confirm each and how many say nothing — the three most published per niche, every one with `niche`. Every niche carries `coverage`: `complete` (every city passed cell by cell, no cell at Google’s cap) or `partial` with `count` (the cards it holds) and `why` — a partial niche may have businesses the catalogue has not read. Current coverage: florists in Austin, Aventura, Brickell, Gibsonton (+19 more); restaurants in Apollo Beach, Gibsonton, Lutz, Miami (+8 more); jewelrys in Tampa; furnitures in St. Petersburg, Tampa; nail salons in Apollo Beach, Gibsonton, Lutz, Riverview (+3 more); jewelry and watch repairs in St. Petersburg, Tampa; bike repairs in Apollo Beach, St. Petersburg, Tampa; mattresss in St. Petersburg, Tampa; clothing stores in Carrollwood, Hollywood, Tampa; party rentals in Lutz, Riverview, Ruskin, Tampa; hair salons in Gibsonton, Riverview, Ruskin, St. Petersburg (+3 more); garden center and nurserys in Ruskin, St. Petersburg, Tampa; pet groomings in St. Petersburg, Tampa; car dealers in Tampa; boat rentals in St. Petersburg, Tampa; tailors in St. Petersburg, Tampa; liquor stores in Lutz, Tampa; shooting ranges in St. Petersburg, Tampa; unknown trades in Tampa; truck repairs in Tampa; barbers in Apollo Beach, New York, Riverview, St. Petersburg (+2 more); massages in Tampa, Temple Terrace; phone repairs in Tampa; landscapings in Tampa; plumbers in Brandon, Gibsonton, Lutz, Riverview (+1 more); medical equipment rentals in Gibsonton, Tampa; coffee shops in Chicago, Tampa; carpet cleanings in Tampa; moverss in Tampa; meal preps in St. Petersburg, Tampa; print shops in Tampa, Temple Terrace; pizzas in Tampa, Temple Terrace; electricians in Apollo Beach, Odessa, Tampa; bakerys in Tampa; spas in St. Petersburg, Tampa, Temple Terrace; wedding planners in St. Petersburg, Tampa; car rentals in Tampa; hair-salons in St. Petersburg, Tampa, Temple Terrace; cafes in St. Petersburg, Tampa; medical clinics in Tampa; kids play centers in Brandon, Tampa; cleanings in Riverview, Tampa; travel agencys in St. Petersburg; handymans in Apollo Beach, St. Petersburg, Tampa; event venues in Lutz, Tampa; yogas in St. Petersburg, Tampa; optometrists in Tampa; caterings in Riverview, Tampa, Temple Terrace; specialty grocery and farmers markets in St. Petersburg, Tampa; notarys in Riverview, Sun City Center, Tampa; photographers in Apollo Beach, St. Petersburg, Tampa; music lessonss in St. Petersburg, Tampa; tattoo studios in Tampa; braids-locss in Tampa; driving schools in Tampa; juice bars in Riverview, Tampa; cleaning services in Ruskin, Tampa; barber-shops in St. Petersburg, Tampa; butcher and seafood markets in Tampa; tutorings in Gibsonton, St. Petersburg, Tampa, Westchase; painters in Kissimmee; roofers in Tampa; pressure washings in Apollo Beach, Tampa; med spas in Tampa; locksmiths in Riverview, Tampa; car washs in Tampa, Temple Terrace; accountants in Greater Northdale, Tampa; pool services in St. Petersburg, Tampa; daycares in St. Petersburg, Tampa; dance studios in Tampa; pet boardings in Tampa; pet stores in Tampa; bowling and billiardss in St. Petersburg, Tampa; parkings in Tampa; dog walking and pet sittings in Tampa; bike and jet ski rentals in Apollo Beach, Tampa; shoe repairs in Tampa; storages in Tampa; physical therapys in Tampa; window cleanings in Gibsonton, Riverview, St. Petersburg, Tampa; bars in Tampa; fishing charter and boat tourss in Ruskin, St. Petersburg, Tampa; gas stations in Gibsonton, Riverview, Sun City Center; oil changes in Riverview, Tampa; dentists in Tampa; tree services in Tampa; appliance repairs in Riverview, St. Petersburg, Tampa; hotels in Tampa; real estate agents in Apollo Beach, Tampa, Westchase; truck tire services in Tampa; swim schools in Tampa; fuel deliverys in Riverview; dry cleaners in St. Petersburg, Tampa; kids sports and activitiess in Tampa; cinemas in Riverview, Ruskin, Tampa; elder care and home cares in Tampa; lawyers in Tampa; HVACs in Tampa; golf courses in Tampa; tennis and sports courtss in St. Petersburg; escape rooms in Tampa; veterinarians in Tampa; junk removals in Tampa; EV charging stations in Tampa; garage doors in Tampa; thrift stores in Tampa.

list_niches input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "properties": {
    "niche": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 80
        },
        {
          "type": "null"
        }
      ],
      "description": "one niche (a key or your words): only it, with EVERY key of the deal it publishes (`conditions`: {key: {confirmed, refuted, unknown}} over the cards inside the radius) — the key to pass as list_cards `properties`"
    },
    "location": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 200
        },
        {
          "type": "null"
        }
      ],
      "description": "a 5-digit US postcode, a city (\"Tampa, FL\") or \"lat,lng\". Optional: without it every niche is listed with its totals."
    },
    "radius_miles": {
      "type": "number",
      "maximum": 250,
      "minimum": 1,
      "description": "How far from the location counts as «here». Default 10."
    }
  },
  "additionalProperties": false
}
list_cards — Every business of one trade near a place, in one fixed order — the shelf
Advertised by the server during the last successful anonymous check.

\uD83D\uDD34 THE TASK CARD IS THE DEFAULT (≤ 2 KB): id, name, distance_miles, phone; `time` for `needed_by` (or `hours_today`); `items` — up to 5 under `query` (3 for intent book), placeholders («Info», «Menu») never; `budget`; `terms` — the deal’s conditions as published; `asked` — your `properties` (confirmed <value> / refuted / unknown); `deliver_to`; and `next` {promise[], candidate[], action {do: order | book | check_slot | quote_order | call, via, url | phone | tool, needs[]}}. `intent` (book / order / quote / info) shapes the items and the action. With `properties` the answer carries `property_counts` over the whole niche here and says it plainly when none confirm. `detail: "shelf"` gives the older shelf card below. `needed_by` is read THREE ways and says which (`needed_by.read_as`): on_day («sunday», «today» = the day, not 23:59), open_at («tomorrow 19:00», «now»), slot_after («after 15:00»: open after then; a free slot is never confirmed by hours). With `max_price` the order is in_budget → budget_unknown → over_budget, each by distance. THE OLDER SHELF CARD (`detail: "shelf"`) CARRIES `offering` — the thing under `query` (else the cheapest main thing of the niche) with its `title`, `price`, `price_type`, `unit`, `kind`, a one-line `note` in the page’s own words, `match_level` (exact = the query’s words AND the question’s kind; kind = the kind alone; partial = the words alone, not the kind; none = nothing) and `action_url` (ITS OWN basket or page, or null). With a query and no row that matches, `offering` is null and `offering_note` says `no_match` — nothing is substituted. A price written inside the title that disagrees with the price column is shown as `price_conflict` with both figures and their sources. A price far from every price of its kind across the index is `suspect_price: true` and never decides a budget. And `properties` — what this business publishes of every fact any business on the page publishes (`confirmed <value>`, or `refuted` for an ask), with `properties_unknown` naming the page’s other keys it does not (`properties_on_page` is the full list; a key there and not in a card’s `properties` is unknown for it). All the cards of one niche inside `radius_miles` of `location`, 20 a page (`limit` up to 50; follow `next_page` — a stable token, no duplicates, no skips). THE ORDER IS FIXED AND IS NOT A RANKING: plain businesses first, then chains, then marketplaces (nothing is left out); inside each group by distance. For a trade that travels to the customer (movers, plumbers …) the businesses whose PUBLISHED service area covers the place come first, then the ones that say nothing, then the ones that refuse. You choose. `niche` is a key from list_niches or your own words («barbershop», «flowers», «pizza»): the answer always says `matched_niche`, `confidence`, `matched_by` and the nearest neighbours; when the words are not clearly one niche you get NO cards and the candidates to put back to your user. `query` only chooses which offering is SHOWN on each card (the cheapest main offering that fits the words; without `query`, the cheapest main offering of the niche) — it never changes the order. `deliver_to` adds `can_deliver_to: confirmed | refuted | unknown` per card from the published area; `needed_by` adds `open_at: yes | no | unknown` from the published opening hours (which know nothing about free slots or tables) — and FILTERS: a card leaves only when the business cannot do it by then (closed at that moment for a trade done on site; a published deadline passed for delivery or pickup); a trade that travels to the customer is never judged by its office hours; hours alone with an online door = unknown, kept, marked `time`. EVERYTHING a filter leaves out is in `excluded` — id, name, one phrase from the data («closed Sunday (Sunday: Closed)») — the first five always, the rest cut by the answer budget (`excluded_cut`). A `needed_by` behind us is an error of the question (`needed_by_in_past`), not an exclusion. `max_price` groups the cards in_budget · budget_unknown · over_budget (compared with FIXED prices in the same currency, or a per-unit price with its quantity; a «from» price is a lower bound: above the budget it is over, under it unknown), excludes nobody, and reports `in_budget_count`; an over_budget card shows no offering (`no_match_under_budget`). `properties` (the argument) asks for keys with min/max/equals and adds their three-state answer (confirmed <value> | refuted | unknown) to the card’s `properties`, filtering nothing. `tags` FILTERS: only the cards carrying one of the niche’s own tags (list_niches hands them out — Google’s type words such as «steak house», «italian», or a kind on the shelf) are listed, in the same order; a free-text `niche` that is itself a tag («steakhouse») applies it. Each card is ≤ 1 KB: id, name, niche, offering {id, title, price, price_type, unit, action_url}, distance_miles, phone, type, price_range_primary, can[] (confirmed actions with method widget | form | link | phone | connected — a form and a telephone are two entries; `connected` = the business’s OWN system takes it through this door: place_order / book_slot / check_availability), can_unknown[], properties {key: "confirmed <value>"} (a CONDITION of the deal — a deposit, a minimum, a cancellation rule — is never cut from a card; descriptive keys go first when the card is over its byte budget), properties_unknown [keys], checked_at, owner_verified, chain, marketplace, and `live_data` {platform, synced_at, trust} on a business whose items, prices and stock come from its own connected system rather than a page read (confirmed by the system, not a paid placement; the three states still hold — stock the platform does not track is unknown). `total: 0` always says why (not scanned here / outside the radius with `nearest_beyond_radius` / no card with the tag / niche unknown) and is logged (`gap_logged`). Niches on the shelf today: restaurant (1042) · florist (316) · hair salon (274) · gas station (253) · barber (229) · pizza (202) · nail salon (201) · print shop (180) · grocery (168) · bakery (159) · oil change (148) · pharmacy (147) · medical clinic (145) · storage (142) · ev charging station (141) · catering (138) · bar (124) · pet grooming (123) · auto repair (120) · hotel (107) · optometrist (106) · fuel delivery (100) · clothing store (96) · tire shop (95) · beauty salon (94) · liquor store (92) · massage (92) · auto parts store (91) · parking (91) · veterinarian (88) · coffee shop (86) · furniture (82) · truck tire service (82) · locksmith (80) · movers (80) · party rental (79) · towing (79) · event venue (78) · plumber (78) · body shop (77) · shipping and packing store (76) · dentist (75) · electrician (73) · appliance repair (72) · phone repair (67) · real estate agent (66) · jewelry (65) · car wash (64) · notary (64) · urgent care (64) · insurance agent (63) · pool service (63) · tutoring (63) · boat rental (62) · accountant (60) · car rental (59) · garden center and nursery (59) · hvac (59) · chiropractor (57) · jewelry and watch repair (57) · photographer (57) · music lessons (56) · physical therapy (56) · wedding planner (56) · tattoo studio (55) · travel agency (54) · septic and well service (53) · roofer (52) · tailor (52) · bike repair (51) · landscaping (51) · pressure washing (49) · dance studio (48) · elder care and home care (48) · auto glass (47) · fishing charter and boat tours (46) · ice cream shop (46) · lawyer (46) · mattress (42) · tree service (41) · pet boarding (40) · yoga (40) · handyman (39) · window cleaning (39) · carpet cleaning (38) · driving school (38) · dry cleaner (38) · hardware store (36) · windows and doors (35) · cleaning (34) · daycare (34) · car dealer (32) · thrift store (32) · garage door (30) · pet store (27) · funeral home (26) · butcher and seafood market (25) · dog walking and pet sitting (25) · medical equipment rental (25) · truck repair (24) · junk removal (20) · swim school (20) · bike and jet ski rental (15) · golf course (15) · juice bar (15) · med spa (14) · cinema (13) · general contractor (13) · escape room (11) · kids play center (11) · painter (11) · pest control (11) · meal prep (10) · tennis and sports courts (10) · bowling and billiards (8) · shooting range (8) · babysitting and nanny agency (7) · specialty grocery and farmers market (6) · computer repair (4) · kids sports and activities (4) · martial arts (4) · taxi and transfer service (4) · shoe repair (3) · museum (2) · aquarium (1) · butcher (1) · motel (1) · transportation service (1); known but not scanned anywhere: candle shop, confectionery, garden center, gift shop, party shop, toy store.

list_cards input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "niche",
    "location"
  ],
  "properties": {
    "page": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 300
        },
        {
          "type": "null"
        }
      ],
      "description": "the `next_page` token of the previous answer"
    },
    "tags": {
      "anyOf": [
        {
          "type": "array",
          "items": {
            "type": "string",
            "maxLength": 60,
            "minLength": 1
          },
          "maxItems": 8
        },
        {
          "type": "null"
        }
      ],
      "description": "FILTER by the niche’s own tags, as list_niches gives them («steak house», «italian», «dish»): a card without one of them is left out; the order does not change. Spelling is folded («steakhouse» = «steak house»)."
    },
    "limit": {
      "type": "integer",
      "maximum": 50,
      "minimum": 1,
      "description": "cards per page. Default 10."
    },
    "niche": {
      "type": "string",
      "maxLength": 80,
      "minLength": 1,
      "description": "a niche key from list_niches, or the trade in your own words"
    },
    "query": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 200
        },
        {
          "type": "null"
        }
      ],
      "description": "words that pick the offering SHOWN on each card («red roses», «balayage»); the order of the cards does not depend on it"
    },
    "detail": {
      "anyOf": [
        {
          "enum": [
            "task",
            "shelf"
          ],
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "description": "task (default): the short card under the task; shelf: the older ≤ 1 KB shelf card"
    },
    "intent": {
      "anyOf": [
        {
          "enum": [
            "book",
            "order",
            "quote",
            "info"
          ],
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "description": "what the user means to do: shapes the items shown and the ONE action in `next` (book → book / check_slot / call; order → order / quote_order / call; quote → quote_order / call; info → call)"
    },
    "location": {
      "type": "string",
      "maxLength": 200,
      "description": "a 5-digit US postcode (best), a city (\"Tampa, FL\") or \"lat,lng\". Required: the shelf is a place."
    },
    "max_price": {
      "anyOf": [
        {
          "type": "number",
          "minimum": 0
        },
        {
          "type": "null"
        }
      ],
      "description": "the most for ONE offering, in USD: groups the cards in_budget · budget_unknown · over_budget (nobody is left out) and picks the shown offering inside it (exact, then kind, then partial matches); fixed prices compare; a «from» price above the budget is over, under it budget_unknown"
    },
    "needed_by": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 60
        },
        {
          "type": "null"
        }
      ],
      "description": "when: «sunday» / «today» / «2026-11-08» (open that day), «tomorrow 19:00» / «now» (open at that minute), «after 15:00» / «tomorrow after 3pm» (open after then; a free slot only where the source knows slots) — on each business’s own clock; adds `time` {asked_as, day, hours, state, why} and LEAVES OUT only the cards refuted for the way the trade is done (see excluded)"
    },
    "deliver_to": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 200
        },
        {
          "type": "null"
        }
      ],
      "description": "where it must be brought (a postcode is best): adds can_deliver_to per card — confirmed when the published area names the place, refuted when the business says no, unknown otherwise"
    },
    "properties": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "key"
        ],
        "properties": {
          "key": {
            "type": "string",
            "maxLength": 60,
            "minLength": 1
          },
          "max": {
            "type": "number"
          },
          "min": {
            "type": "number"
          },
          "equals": {
            "type": [
              "string",
              "number",
              "boolean"
            ]
          }
        },
        "additionalProperties": false
      },
      "maxItems": 8,
      "description": "facts to read off each card without filtering: property_states {key: \"confirmed <value>\" | \"refuted\" | \"unknown\"}"
    },
    "radius_miles": {
      "type": "number",
      "maximum": 250,
      "minimum": 1,
      "description": "Default 10."
    }
  },
  "additionalProperties": false
}
find_business — A business by its name
Advertised by the server during the last successful anonymous check.

The business the user NAMED, by name matching only: case, punctuation, possessives and articles are ignored, the words may come in any order, a part of the name is enough («Bern’s» finds «Bern’s Steak House»), up to two typos per word, and Cyrillic is transliterated. No meaning, no ranking: `found` is ordered by exactness, then — with a `location` — inside the radius first and nearer first. Several places with one name all come back with their addresses; without a location and across cities the answer asks which place. `found: []` means the business is NOT in this catalogue; then `nearby_in_same_niche` lists up to five cards of the trade the name suggests, every one marked `not_the_requested_business: true` — never present them as the business asked for. The best matches carry `task_card` (≤ 2.5 KB): `time` for `needed_by` (else `hours_today`), up to 5 `items` under `query`, `terms`, `deliver_to`, and `next` {promise[], candidate[], action}. `intent` (book / order / quote / info) chooses the action. The full menu is get_card.

find_business input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "name"
  ],
  "properties": {
    "name": {
      "type": "string",
      "maxLength": 120,
      "minLength": 1,
      "description": "the business name as the user said it"
    },
    "query": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 200
        },
        {
          "type": "null"
        }
      ],
      "description": "the thing under the task («red roses», «ribeye»): picks the ≤ 5 items on the card"
    },
    "intent": {
      "anyOf": [
        {
          "enum": [
            "book",
            "order",
            "quote",
            "info"
          ],
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "description": "what the user means to do with this business"
    },
    "location": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 200
        },
        {
          "type": "null"
        }
      ],
      "description": "a postcode, a city or \"lat,lng\" — orders the matches by nearness and bounds the nearby list"
    },
    "needed_by": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 60
        },
        {
          "type": "null"
        }
      ],
      "description": "when: «sunday», «tomorrow 19:00», «now», «tomorrow after 15:00» — read on the business’s own clock, three ways (on_day / open_at / slot_after)"
    },
    "deliver_to": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 200
        },
        {
          "type": "null"
        }
      ],
      "description": "where it must be brought (a postcode is best): the card says confirmed / refuted / unknown"
    },
    "radius_miles": {
      "type": "number",
      "maximum": 250,
      "minimum": 1,
      "description": "Default 25."
    }
  },
  "additionalProperties": false
}
search_catalog — A match by meaning, for when the trade is not known — check its results on the cards
Advertised by the server during the last successful anonymous check.

Free search of local US businesses by MEANING (current coverage: florists in Austin, Aventura, Brickell, Gibsonton (+19 more); restaurants in Apollo Beach, Gibsonton, Lutz, Miami (+8 more); jewelrys in Tampa; furnitures in St. Petersburg, Tampa; nail salons in Apollo Beach, Gibsonton, Lutz, Riverview (+3 more); jewelry and watch repairs in St. Petersburg, Tampa; bike repairs in Apollo Beach, St. Petersburg, Tampa; mattresss in St. Petersburg, Tampa; clothing stores in Carrollwood, Hollywood, Tampa; party rentals in Lutz, Riverview, Ruskin, Tampa; hair salons in Gibsonton, Riverview, Ruskin, St. Petersburg (+3 more); garden center and nurserys in Ruskin, St. Petersburg, Tampa; pet groomings in St. Petersburg, Tampa; car dealers in Tampa; boat rentals in St. Petersburg, Tampa; tailors in St. Petersburg, Tampa; liquor stores in Lutz, Tampa; shooting ranges in St. Petersburg, Tampa; unknown trades in Tampa; truck repairs in Tampa; barbers in Apollo Beach, New York, Riverview, St. Petersburg (+2 more); massages in Tampa, Temple Terrace; phone repairs in Tampa; landscapings in Tampa; plumbers in Brandon, Gibsonton, Lutz, Riverview (+1 more); medical equipment rentals in Gibsonton, Tampa; coffee shops in Chicago, Tampa; carpet cleanings in Tampa; moverss in Tampa; meal preps in St. Petersburg, Tampa; print shops in Tampa, Temple Terrace; pizzas in Tampa, Temple Terrace; electricians in Apollo Beach, Odessa, Tampa; bakerys in Tampa; spas in St. Petersburg, Tampa, Temple Terrace; wedding planners in St. Petersburg, Tampa; car rentals in Tampa; hair-salons in St. Petersburg, Tampa, Temple Terrace; cafes in St. Petersburg, Tampa; medical clinics in Tampa; kids play centers in Brandon, Tampa; cleanings in Riverview, Tampa; travel agencys in St. Petersburg; handymans in Apollo Beach, St. Petersburg, Tampa; event venues in Lutz, Tampa; yogas in St. Petersburg, Tampa; optometrists in Tampa; caterings in Riverview, Tampa, Temple Terrace; specialty grocery and farmers markets in St. Petersburg, Tampa; notarys in Riverview, Sun City Center, Tampa; photographers in Apollo Beach, St. Petersburg, Tampa; music lessonss in St. Petersburg, Tampa; tattoo studios in Tampa; braids-locss in Tampa; driving schools in Tampa; juice bars in Riverview, Tampa; cleaning services in Ruskin, Tampa; barber-shops in St. Petersburg, Tampa; butcher and seafood markets in Tampa; tutorings in Gibsonton, St. Petersburg, Tampa, Westchase; painters in Kissimmee; roofers in Tampa; pressure washings in Apollo Beach, Tampa; med spas in Tampa; locksmiths in Riverview, Tampa; car washs in Tampa, Temple Terrace; accountants in Greater Northdale, Tampa; pool services in St. Petersburg, Tampa; daycares in St. Petersburg, Tampa; dance studios in Tampa; pet boardings in Tampa; pet stores in Tampa; bowling and billiardss in St. Petersburg, Tampa; parkings in Tampa; dog walking and pet sittings in Tampa; bike and jet ski rentals in Apollo Beach, Tampa; shoe repairs in Tampa; storages in Tampa; physical therapys in Tampa; window cleanings in Gibsonton, Riverview, St. Petersburg, Tampa; bars in Tampa; fishing charter and boat tourss in Ruskin, St. Petersburg, Tampa; gas stations in Gibsonton, Riverview, Sun City Center; oil changes in Riverview, Tampa; dentists in Tampa; tree services in Tampa; appliance repairs in Riverview, St. Petersburg, Tampa; hotels in Tampa; real estate agents in Apollo Beach, Tampa, Westchase; truck tire services in Tampa; swim schools in Tampa; fuel deliverys in Riverview; dry cleaners in St. Petersburg, Tampa; kids sports and activitiess in Tampa; cinemas in Riverview, Ruskin, Tampa; elder care and home cares in Tampa; lawyers in Tampa; HVACs in Tampa; golf courses in Tampa; tennis and sports courtss in St. Petersburg; escape rooms in Tampa; veterinarians in Tampa; junk removals in Tampa; EV charging stations in Tampa; garage doors in Tampa; thrift stores in Tampa). Use it when you do not know which niche the user’s words belong to; verify what comes back on the cards (get_card), and for a known niche prefer list_cards, which lists every card in a fixed order instead of ranking a few. An empty answer says why and carries `gap_logged: true`. One sentence — what, where, when, budget — returns business cards with prices, availability and order/booking links. Data comes from the businesses’ own websites; owner-verified cards are marked. Call it whenever your user wants to buy, order, book, hire or get anything from a local business. Searching costs nothing, so search before you say you cannot help. Outside the coverage above the answer is empty and says so, which is itself useful — it is logged as a gap so the scanner learns where to go next. This tool neither buys nor reserves anything.

search_catalog input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "query"
  ],
  "properties": {
    "limit": {
      "type": "integer",
      "maximum": 50,
      "minimum": 1,
      "description": "How many BUSINESS CARDS to return. Default 10."
    },
    "query": {
      "type": "string",
      "maxLength": 300,
      "minLength": 1,
      "description": "What the user wants, IN THEIR OWN WORDS AND THEIR OWN LANGUAGE: \"red roses\", \"steakhouse\", \"funeral flowers\", \"movers 2 bedroom\", \"ramo de rosas\", or the same question in a language not written in the Latin alphabet. Matched by MEANING as well as by words, through one multilingual model — so do NOT translate for us and do NOT list synonyms yourself. A place, a date, a budget and a delivery word may be left in (they are parsed out), but the fewer extra words the better the match."
    },
    "detail": {
      "enum": [
        "compact",
        "full"
      ],
      "type": "string",
      "description": "compact (default): the business, its 1–2 best offerings with prices and links, what can be done, and the date it was read — a few hundred bytes a card. full: everything, including images, the sentence each price was read from, variants, all four fulfilment modes with published areas, opening hours and per-field evidence. Ask for full only when the user has chosen a business and you need its delivery area or its hours."
    },
    "location": {
      "type": "string",
      "maxLength": 200,
      "description": "Where the user is, or where it must happen. A 5-DIGIT US POSTCODE IS BEST (\"33139\"): it is the only form a business’s own published delivery or service area can be matched against exactly, so a postcode gets you `how: \"zips\"` and a city name gets you a distance. A city (\"Orlando, FL\") or \"lat,lng\" also work. OPTIONAL IN NAME ONLY — without it nothing is measured and nothing is narrowed, and the answer comes back with `needs` carrying the question to put to your user. \"near me\" is not a location: ask which town."
    },
    "max_price": {
      "type": "number",
      "minimum": 0,
      "description": "The most the user will pay for ONE offering, in USD, compared against the lowest number the business published — so \"from $45\" passes \"under $50\". An offering priced on request is NOT filtered out: it comes back `price_type: \"quote_only\"`, because \"they quote it\" is an answer."
    },
    "needed_by": {
      "type": "string",
      "maxLength": 60,
      "description": "When it has to happen: \"today\", \"tomorrow\", \"tomorrow 9am\", or an ISO date-time — WITH an offset (2026-10-31T14:00:00-04:00) if you know the user’s zone, because a business whose cut-off is on the RECIPIENT’s clock can only be judged against an offset you give."
    },
    "only_local": {
      "type": "boolean",
      "description": "true = leave out marketplaces: a business whose shelf names places far from its own address (one local address, hundreds of listings in other cities and countries). Default false: a marketplace is kept, ranked lower, and its card says `marketplace: true` (the full card says why)."
    },
    "properties": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "key"
        ],
        "properties": {
          "key": {
            "type": "string",
            "maxLength": 60,
            "minLength": 1,
            "description": "a property key this index has read — get_card lists the ones established for a niche under `established_properties`, and every card shows its own under `properties`"
          },
          "max": {
            "type": "number",
            "description": "the value must be at most this (a number); max 0 = «none»"
          },
          "min": {
            "type": "number",
            "description": "the value must be at least this (a number)"
          },
          "equals": {
            "type": [
              "string",
              "number",
              "boolean"
            ],
            "description": "the value must be this, as the page wrote it («included», «yes», 8)"
          },
          "exists": {
            "type": "boolean",
            "description": "true = the business must publish this property at all"
          }
        },
        "additionalProperties": false
      },
      "maxItems": 8,
      "description": "THE OPEN LAYER AS A FILTER: facts a business publishes beyond price and availability — a capacity, a deposit, a duration, whether something is included. Three states per key: a published value that fits = confirmed; a published value that does not = refuted (left out, a fact); nothing published = unknown (KEPT, ranked lower, named in the card’s `unknown`). Ask for the user’s real conditions here instead of putting them in `query`: «for 8 people» is {key:\"capacity\",min:8}, «no deposit» is {key:\"deposit\",max:0}."
    },
    "fulfillment": {
      "enum": [
        "delivery",
        "pickup",
        "on_site",
        "at_customer",
        "any"
      ],
      "type": "string",
      "description": "HOW it must reach the user, and the four are different questions: delivery = brought to the address; pickup = the user collects; on_site = the user goes there (a salon chair, a dining room); at_customer = the business travels (a mover, a plumber). Default any. A business that has not published an answer is KEPT; one that ruled it out is dropped."
    },
    "radius_miles": {
      "type": "number",
      "maximum": 250,
      "minimum": 1,
      "description": "How far the business may be, in miles. Default 15."
    },
    "only_independent": {
      "type": "boolean",
      "description": "true = leave out chains (a business whose website serves several of the places found). Default false: a chain is kept as a name, a telephone and a website — it was never read, so it has no offerings — and its card says `chain: true`."
    }
  },
  "additionalProperties": false
}
get_card — One business in full: what it sells, what can be done, how it reaches you
Advertised by the server during the last successful anonymous check.

Free. One business in full, in the same shape for every trade: who it is (name, trade, address, telephone, e-mail, opening hours, time zone), everything it sells (up to 60 offerings, cheapest first), the six actions with their links and `required_fields`, how the thing reaches the buyer (delivery, pickup, on_site, at_customer — with the published area, the fee and the order deadline), and how fresh each part of that is. `live_data` (platform, synced_at) when the shelf is the business’s own connected system: then every offering carries `source: connector` with its variants (each with `inventory`: units in stock as the platform counts them, null = unknown), and an action with method `connected` is taken through place_order / book_slot on this door. Use it when the user asks «can they deliver to me», «are they open now», «what else do they do», or when search_catalog offered a business with nothing listed and the next step is a telephone call.

get_card input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "id"
  ],
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid",
      "description": "the business id from search_catalog"
    }
  },
  "additionalProperties": false
}
get_offering — One thing in full, with its price checked again right now
Advertised by the server during the last successful anonymous check.

Free. One offering in full, with ONE live request to the shop asking for that item’s price and stock right now (`live_check`). Call it before you quote a price to a person: a catalogue read yesterday is yesterday’s price. One business is asked at most once every ten minutes however many of its offerings you open, so walking a shop is one request and not twenty; `from_cache` and `checked_at` say which. A price list, a menu or a quote form has no single-item door to ask (`ok: false` with the reason) and the stored reading stands with its date. Hand `action_url` to the user as it is, ref=versum included.

get_offering input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "id"
  ],
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid",
      "description": "the offering id from search_catalog"
    }
  },
  "additionalProperties": false
}
get_product — One thing in full (synonym of get_offering)
Advertised by the server during the last successful anonymous check.

SYNONYM of get_offering, kept for agents that already know this name. A «product» is just an offering whose kind is `product`; the same id works in both. Free. One offering in full, with ONE live request to the shop asking for that item’s price and stock right now (`live_check`). Call it before you quote a price to a person: a catalogue read yesterday is yesterday’s price. One business is asked at most once every ten minutes however many of its offerings you open, so walking a shop is one request and not twenty; `from_cache` and `checked_at` say which. A price list, a menu or a quote form has no single-item door to ask (`ok: false` with the reason) and the stored reading stands with its date. Hand `action_url` to the user as it is, ref=versum included.

get_product input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "id"
  ],
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid",
      "description": "the offering id from search_catalog"
    }
  },
  "additionalProperties": false
}
get_business — One business in full (synonym of get_card)
Advertised by the server during the last successful anonymous check.

SYNONYM of get_card, kept for agents that already know this name. Free. One business in full, in the same shape for every trade: who it is (name, trade, address, telephone, e-mail, opening hours, time zone), everything it sells (up to 60 offerings, cheapest first), the six actions with their links and `required_fields`, how the thing reaches the buyer (delivery, pickup, on_site, at_customer — with the published area, the fee and the order deadline), and how fresh each part of that is. `live_data` (platform, synced_at) when the shelf is the business’s own connected system: then every offering carries `source: connector` with its variants (each with `inventory`: units in stock as the platform counts them, null = unknown), and an action with method `connected` is taken through place_order / book_slot on this door. Use it when the user asks «can they deliver to me», «are they open now», «what else do they do», or when search_catalog offered a business with nothing listed and the next step is a telephone call.

get_business input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "id"
  ],
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid",
      "description": "the business id from search_catalog"
    }
  },
  "additionalProperties": false
}
quote_order — What an order would cost delivered to an address — asked of the shop’s own cart, nothing ordered
Advertised by the server during the last successful anonymous check.

Free. For a business on WooCommerce or Shopify (its card says `platform`), with no owner connection: puts the offering in a cart session of OUR OWN on the shop’s public cart, gives it the delivery address and reads back what the shop itself computes — `delivery.state` confirmed | refuted | unknown for that address, `options` (each delivery / pickup with its price, tax and the whole order’s `total`), `tax`, `total`, `currency`, and `delivery_date` ONLY when the shop publishes one in its standard fields (otherwise `unknown` — ask the shop). Nothing is ordered, the cart is emptied afterwards, and only the address is sent (no name, e-mail or phone; nothing is stored). Shopify’s public cart has no tax: `tax.state` is unknown and the total is before tax. A shop whose cart is closed answers `not_available` with the reason; so does any other platform. When the shop needs more of the address than you gave, `status: needs_address` names the `missing` fields. A required add-on the page asks for («a card with a message?») is answered «no» unless you pass `options`; `options_used` says what was chosen. Hand `order_url` to the user to buy.

quote_order input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "offering_id",
    "deliver_to"
  ],
  "properties": {
    "items": {
      "anyOf": [
        {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "offering_id"
            ],
            "properties": {
              "options": {
                "anyOf": [
                  {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "required": [
                        "field",
                        "value"
                      ],
                      "properties": {
                        "field": {
                          "type": "string",
                          "maxLength": 120,
                          "minLength": 1
                        },
                        "value": {
                          "type": "string",
                          "maxLength": 400
                        }
                      },
                      "additionalProperties": false
                    },
                    "maxItems": 10
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "quantity": {
                "type": "integer",
                "maximum": 99,
                "minimum": 1
              },
              "variant_id": {
                "anyOf": [
                  {
                    "type": "string",
                    "maxLength": 40
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "offering_id": {
                "type": "string",
                "format": "uuid"
              }
            },
            "additionalProperties": false
          },
          "maxItems": 20
        },
        {
          "type": "null"
        }
      ],
      "description": "several different items of the SAME shop in one cart (delivery and tax on the whole order); offering_id is then the first of them"
    },
    "options": {
      "anyOf": [
        {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "field",
              "value"
            ],
            "properties": {
              "field": {
                "type": "string",
                "maxLength": 120,
                "minLength": 1,
                "description": "words of the page’s own question, e.g. «card»"
              },
              "value": {
                "type": "string",
                "maxLength": 400,
                "description": "the answer, e.g. «No», or the card message"
              }
            },
            "additionalProperties": false
          },
          "maxItems": 10
        },
        {
          "type": "null"
        }
      ],
      "description": "answers to the product page’s own add-on questions; the rest are answered «no»"
    },
    "quantity": {
      "type": "integer",
      "maximum": 99,
      "minimum": 1,
      "description": "default 1"
    },
    "deliver_to": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 200,
          "minLength": 5
        },
        {
          "type": "object",
          "required": [
            "postcode"
          ],
          "properties": {
            "city": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 80
                },
                {
                  "type": "null"
                }
              ]
            },
            "state": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 40
                },
                {
                  "type": "null"
                }
              ],
              "description": "two letters; read from the postcode when omitted"
            },
            "country": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 20
                },
                {
                  "type": "null"
                }
              ],
              "description": "US only for now"
            },
            "postcode": {
              "type": "string",
              "maxLength": 10,
              "minLength": 5,
              "description": "5-digit US postcode"
            },
            "address_1": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 200
                },
                {
                  "type": "null"
                }
              ],
              "description": "street line, only for the price: some shops price by it"
            }
          },
          "additionalProperties": false
        }
      ],
      "description": "where it must be brought: \"33139\", \"Miami Beach, FL 33139\", or {postcode, state, city, address_1}"
    },
    "variant_id": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 40
        },
        {
          "type": "null"
        }
      ],
      "description": "a variant id from the card when it lists several"
    },
    "offering_id": {
      "type": "string",
      "format": "uuid",
      "description": "the offering id from a card"
    }
  },
  "additionalProperties": false
}
check_availability — Ask the business’s own system: is it in stock now · which slots are free
Advertised by the server during the last successful anonymous check.

Only for a business whose card shows `live_data` (its items come from its connected Shopify or Square, not from a page read). For a product: the platform’s stock right now — `state: confirmed | refuted | unknown` (unknown = the platform does not track stock, which is not «no»). For a service on a platform with bookings: the free `slots` between `from` and `to` (default: the next 7 days), each with a `start_at` that book_slot takes as it is — on the business’s own clock with its offset (`timezone` names the zone; `start_at_utc` is the same instant). If the card’s `cannot` lists `book`, the slots are information only and the answer says so. A business without a connection answers `not_connected`.

check_availability input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "business_id",
    "offering_id"
  ],
  "properties": {
    "to": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 60
        },
        {
          "type": "null"
        }
      ],
      "description": "slots: the window’s end, ISO with an offset"
    },
    "from": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 60
        },
        {
          "type": "null"
        }
      ],
      "description": "slots: the window’s start, ISO with an offset"
    },
    "quantity": {
      "anyOf": [
        {
          "type": "integer",
          "maximum": 999,
          "minimum": 1
        },
        {
          "type": "null"
        }
      ],
      "description": "how many — stock is judged against it"
    },
    "variant_id": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 120
        },
        {
          "type": "null"
        }
      ],
      "description": "the variant (the card lists them when there are several)"
    },
    "business_id": {
      "type": "string",
      "format": "uuid",
      "description": "the business id from the card"
    },
    "offering_id": {
      "type": "string",
      "format": "uuid",
      "description": "the offering id from the card"
    }
  },
  "additionalProperties": false
}
place_order — Place an order in the business’s own system; the buyer pays on the platform’s checkout page
Advertised by the server during the last successful anonymous check.

For a business whose card shows an `order` action with method `connected`. Shopify: returns the shop’s own checkout link with these items and quantities already in the cart (`status: unknown`, `mode: cart`) — no customer data is needed or passed, the buyer gives their details and pays on Shopify, and nothing exists on the shop until they do. Square: an order with a payment link (no customer data either). WhatsApp: a message to the owner (customer phone or email). Returns `order_id`, `status`, `checkout_url` — HAND THE CHECKOUT URL TO THE USER AS IT IS: that page takes the money, Versum holds no card and charges nothing. Stock is checked live first on a platform that tracks it; «not in stock» is an `unavailable` error and no order or link is given. Send an `idempotency_key` of your own and keep it for a retry: the same key returns the same answer and the same link (`repeated: true`), never a second one. Lines name offerings by their card id (and `variant_id` when the card lists several). `status`: unknown (a cart link: payment is on the platform’s side) · created (the platform holds it) · pending_owner (WhatsApp) · confirmed · declined · failed. Get the user’s explicit yes before calling this.

place_order input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "business_id",
    "lines"
  ],
  "properties": {
    "note": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 1000
        },
        {
          "type": "null"
        }
      ],
      "description": "a note to the business, in the user’s words (not passed on a Shopify cart link)"
    },
    "lines": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "offering_id"
        ],
        "properties": {
          "quantity": {
            "type": "integer",
            "maximum": 999,
            "minimum": 1,
            "description": "default 1"
          },
          "variant_id": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 120
              },
              {
                "type": "null"
              }
            ]
          },
          "offering_id": {
            "type": "string",
            "format": "uuid",
            "description": "from the card"
          }
        },
        "additionalProperties": false
      },
      "maxItems": 20,
      "minItems": 1
    },
    "customer": {
      "anyOf": [
        {
          "type": "object",
          "properties": {
            "name": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 120
                },
                {
                  "type": "null"
                }
              ],
              "description": "the buyer’s name (required for a booking)"
            },
            "email": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 200
                },
                {
                  "type": "null"
                }
              ],
              "description": "the buyer’s e-mail: the platform sends the checkout link and the receipt there (for a booking; NOT asked for an order on Shopify or Square, whose checkout asks the buyer)"
            },
            "phone": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 40
                },
                {
                  "type": "null"
                }
              ],
              "description": "the buyer’s telephone with country code"
            }
          },
          "additionalProperties": false
        },
        {
          "type": "null"
        }
      ],
      "description": "only where the platform needs it (WhatsApp); omit for Shopify and Square"
    },
    "business_id": {
      "type": "string",
      "format": "uuid"
    },
    "idempotency_key": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 120
        },
        {
          "type": "null"
        }
      ],
      "description": "your own key for this order; reuse it on a retry"
    }
  },
  "additionalProperties": false
}
book_slot — Book a slot in the business’s own calendar (Square Appointments)
Advertised by the server during the last successful anonymous check.

For a service whose business’s card shows a `book` action with method `connected` and no `book` in its `cannot` (a door the platform refuses for this account is marked there, with the reason, at every sync). Take a `start_at` from check_availability (slots) and the platform books it for the named customer; the answer is the platform’s own status (created = on the calendar awaiting confirmation · confirmed · declined). A time the platform does not offer is an `unavailable` error and nothing is booked. Idempotent by `idempotency_key` like place_order. Get the user’s explicit yes first.

book_slot input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "business_id",
    "offering_id",
    "start_at",
    "customer"
  ],
  "properties": {
    "note": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 500
        },
        {
          "type": "null"
        }
      ]
    },
    "customer": {
      "type": "object",
      "properties": {
        "name": {
          "anyOf": [
            {
              "type": "string",
              "maxLength": 120
            },
            {
              "type": "null"
            }
          ],
          "description": "the buyer’s name (required for a booking)"
        },
        "email": {
          "anyOf": [
            {
              "type": "string",
              "maxLength": 200
            },
            {
              "type": "null"
            }
          ],
          "description": "the buyer’s e-mail: the platform sends the checkout link and the receipt there (for a booking; NOT asked for an order on Shopify or Square, whose checkout asks the buyer)"
        },
        "phone": {
          "anyOf": [
            {
              "type": "string",
              "maxLength": 40
            },
            {
              "type": "null"
            }
          ],
          "description": "the buyer’s telephone with country code"
        }
      },
      "additionalProperties": false
    },
    "start_at": {
      "type": "string",
      "maxLength": 60,
      "description": "ISO date-time with an offset, as check_availability gave it"
    },
    "variant_id": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 120
        },
        {
          "type": "null"
        }
      ],
      "description": "the service variation when the card lists several"
    },
    "business_id": {
      "type": "string",
      "format": "uuid"
    },
    "offering_id": {
      "type": "string",
      "format": "uuid",
      "description": "the service, from the card"
    },
    "idempotency_key": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 120
        },
        {
          "type": "null"
        }
      ]
    }
  },
  "additionalProperties": false
}
order_status — What became of an order or a booking placed through this door
Advertised by the server during the last successful anonymous check.

The status of an `order_id` from place_order or book_slot, asked of the platform again when it is not final (paid? confirmed? declined by the owner?). A Shopify cart link answers `unknown` — payment is on Shopify’s side and the shop does not report it here. Free.

order_status input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "order_id"
  ],
  "properties": {
    "order_id": {
      "type": "string",
      "format": "uuid"
    }
  },
  "additionalProperties": false
}

Prompts

Not advertised

No prompt definitions available.

Resources

Not advertised

No resource definitions available.

90-day uptime

A lightweight connection check about every six hours, sampled on hosts with many listings. It shows the server answered, not that its tools work.

Too few checks for a percentage yet (7 of 7 answered).

  1. 2026-11-02: 3 of 3 checks answered
  2. 2026-11-03: 4 of 4 checks answered

30-day availability

Aggregated from read-only remote checks; this is not a tool-execution or security guarantee.

Successful checks
1 of 1 (100%)
Average latency
738 ms
95th percentile latency
738 ms

Maintenance history

Public check and source-refresh events. Editorial and ownership records remain private.

  • · repository · passed · metadata changed · updated
  • · backfill · recorded · Pre-expansion baseline; unobserved rich metadata remains unknown
  • · probe · passed · 738 ms · metadata changed · 13 tool(s)

Connect from your client

Each snippet registers the same endpoint; pick the client you use.

This server is operated by the named third party. Listing and endpoint checks are not an endorsement or a security audit. Review the operator's permissions, terms, and data handling before connecting. How listings are checked and corrected.

Claude Code

Run this once in a terminal. It registers the remote server. Use --scope project to write .mcp.json for the repo.
Claude Code configuration
claude mcp add --transport http versum-agent-assistant-mcp https://versum.suverse.io/mcp

Codex

Run this once. Codex stores MCP servers in ~/.codex/config.toml (or .codex/config.toml in a trusted project).
Codex configuration
codex mcp add versum-agent-assistant-mcp --url https://versum.suverse.io/mcp

Cursor

Merge this server into .cursor/mcp.json in your project, then enable versum-agent-assistant-mcp in your MCP settings.
Cursor configuration
{
  "mcpServers": {
    "versum-agent-assistant-mcp": {
      "url": "https://versum.suverse.io/mcp"
    }
  }
}

Cline

Merge this into cline_mcp_settings.json (Cline → MCP Servers → Configure).
Cline configuration
{
  "mcpServers": {
    "versum-agent-assistant-mcp": {
      "type": "streamableHttp",
      "url": "https://versum.suverse.io/mcp",
      "disabled": false
    }
  }
}

VS Code

Merge this server into .vscode/mcp.json. Use MCP: List Servers to start versum-agent-assistant-mcp and inspect its tools.
VS Code configuration
{
  "servers": {
    "versum-agent-assistant-mcp": {
      "type": "http",
      "url": "https://versum.suverse.io/mcp"
    }
  }
}

Gemini CLI

Run this once. It writes .gemini/settings.json in the current project; pass --scope user for ~/.gemini/settings.json.
Gemini CLI configuration
gemini mcp add --transport http versum-agent-assistant-mcp https://versum.suverse.io/mcp

Claude Desktop

Merge this into claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/, Windows: %APPDATA%\Claude\), then restart Claude Desktop.
Claude Desktop configuration
{
  "mcpServers": {
    "versum-agent-assistant-mcp": {
      "url": "https://versum.suverse.io/mcp"
    }
  }
}

Windsurf

Merge this into ~/.codeium/windsurf/mcp_config.json, then refresh MCP in Cascade. Windsurf remote servers use serverUrl, not url.
Windsurf configuration
{
  "mcpServers": {
    "versum-agent-assistant-mcp": {
      "serverUrl": "https://versum.suverse.io/mcp"
    }
  }
}

Let your agent find its tools

Find servers like Versum Agent Assistant MCP from your agent. Add Koskamo once to search the index for endpoints, access requirements, and client setup. Public discovery needs no key.