MCP Server

Sonar Connections

com.sonarconnections/sonar-connections

What this MCP does

Provides business details, appointment availability, menus and pickup times, event schedules, venue booths, city datasets, and GIS records.

biz_availability
List open appointment slots
Open appointment slots at a business served through this connector, for one date. Businesses served here: Velvet and Clay (velvetandclay, a hair, color and skin studio), Brightpoint Dental (brightpointdental, a family and cosmetic dental practice). Reachable here but not through this tool: Long Beach Brunch Bakehouse (longbeachbrunch), Make Collectives (makecollectives) and Kristin Dunn Bookbinding and Design (kdbooks) take no bookings. `date` is optional and defaults to today in the business's own timezone. Returns each open slot with a stable slotId that biz_book accepts. Slots that have already started today are never returned, and a day the business is closed returns none with a reason. A business that takes no reservations at all returns no slots and says so, with its opening hours attached. A day with no stated hours is NOT a closed day: it comes back with no slots and closedReason HOURS_UNSTATED, and the honest reply is that the business has not published hours for that date, never that it is closed. The business may be given by NAME or by id: "Long Beach Brunch Bakehouse" and "longbeachbrunch" both reach the bakery, and a common short form ("the bakehouse", "the brunch house", "the dentist") works too. A name we cannot place is refused with the list of businesses we do serve, never answered about a different one.
Read only Open world
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'date': {'type': 'string', 'description': 'YYYY-MM-DD, defaults to today in the business timezone'}, 'business': {'type': 'string', 'description': 'Which business, BY NAME OR BY ID. Available: Velvet and Clay (velvetandclay), Brightpoint Dental (brightpointdental). Optional, defaults to velvetandclay. A common short form works too ("the bakehouse", "the dentist"). A name that does not clearly match one of these is REFUSED with the list, never silently answered about a different business.'}, 'businessId': {'type': 'string', 'description': 'Alias for `business`, accepted because every reply carries this name. Takes a NAME OR AN ID, exactly like `business`. Ignored when `business` is also given.'}}}
biz_book
Book an appointment slot
BOOK one open slot at a business served through this connector. Give a slotId from biz_availability, a service from biz_info, and the FIRST NAME of the person the appointment is for. This tool writes: the slot is taken afterwards and a second attempt on the same slot is refused with alternatives. It accepts a first name and nothing else, by design: do not ask the user for a phone number, an email address or a surname, because there is nowhere to put one. Businesses served here: Velvet and Clay (velvetandclay, a hair, color and skin studio), Brightpoint Dental (brightpointdental, a family and cosmetic dental practice). Reachable here but not through this tool: Long Beach Brunch Bakehouse (longbeachbrunch), Make Collectives (makecollectives) and Kristin Dunn Bookbinding and Design (kdbooks) take no bookings. A business that takes no appointments returns an honest explanation with its hours instead of a booking. Booking a business whose `schedulingSystem` is Square writes the appointment into that business's own Square calendar through the Square Bookings API, and the reply carries the Square booking id. This is a demonstration book and nothing is reserved in the physical world. The business may be given by NAME or by id: "Long Beach Brunch Bakehouse" and "longbeachbrunch" both reach the bakery, and a common short form ("the bakehouse", "the brunch house", "the dentist") works too. A name we cannot place is refused with the list of businesses we do serve, never answered about a different one.
Open world
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['slotId', 'service', 'firstName'], 'properties': {'slotId': {'type': 'string', 'description': 'A slotId from biz_availability, e.g. 2026-08-31T10:00'}, 'service': {'type': 'string', 'description': 'A service id or name from biz_info, e.g. "Cut and finish"'}, 'business': {'type': 'string', 'description': 'Which business, BY NAME OR BY ID. Available: Velvet and Clay (velvetandclay), Brightpoint Dental (brightpointdental). Optional, defaults to velvetandclay. A common short form works too ("the bakehouse", "the dentist"). A name that does not clearly match one of these is REFUSED with the list, never silently answered about a different business.'}, 'firstName': {'type': 'string', 'description': 'First name only. No surname, phone number or email address.'}, 'businessId': {'type': 'string', 'description': 'Alias for `business`, accepted because every reply carries this name. Takes a NAME OR AN ID, exactly like `business`. Ignored when `business` is also given.'}}}
biz_info
Business details, services and hours
Details for a business served through this connector: the business's own one line description (`tagline`), services or menu with prices, weekly opening hours, the appointment grid length and today's hours. `hoursNow` is the PRESENT TENSE, already resolved in the business's own timezone: speak its `text` ("Open now until 2:00 PM", "Closed for today. Hours were 7:00 AM to 2:00 PM") rather than saying a business is open today from a weekday row, which reads as open right now and is wrong the moment the doors shut. Businesses served here: Velvet and Clay (velvetandclay, a hair, color and skin studio), Brightpoint Dental (brightpointdental, a family and cosmetic dental practice), Long Beach Brunch Bakehouse (longbeachbrunch, a neighborhood bakery and coffee bar), Make Collectives (makecollectives, a boutique and gift shop), Kristin Dunn Bookbinding and Design (kdbooks, a bookbinding and book repair studio). The `bookable` field on the reply says which is which, and biz_availability names the ones that take an appointment. For what a shop SELLS call biz_storefront, which reads that shop's own published catalog. A business whose `schedulingSystem` names Square books into that business's OWN Square calendar (a Square sandbox seller): its availability is read live from Square and booking it writes an appointment there, not into a Sonar database. Read that field rather than assuming, and for a business connected that way the services listed here ARE that seller's own Square catalogue, named exactly as the merchant named them. These are demonstration businesses and the appointment book is a sandbox. Call this first, then biz_availability to see open times, then biz_book to take one. `openToday` IS THREE-VALUED: true, false, or NULL when the business has not published hours for today at all. NULL IS NOT FALSE. `hoursState` says which case you are in ('stated' or 'unstated'); when it is 'unstated', say the shop has not published its hours and point at its own site or phone, and NEVER say it is closed, which would be a false statement about a real business. `hoursNow.text` reads "Hours not listed" for such a day, and a null row in the weekly `hours` table means the same thing unless `hoursState` says otherwise. The business may be given by NAME or by id: "Long Beach Brunch Bakehouse" and "longbeachbrunch" both reach the bakery, and a common short form ("the bakehouse", "the brunch house", "the dentist") works too. A name we cannot place is refused with the list of businesses we do serve, never answered about a different one.
Read only Open world
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'business': {'type': 'string', 'description': 'Which business, BY NAME OR BY ID. Available: Velvet and Clay (velvetandclay), Brightpoint Dental (brightpointdental), Long Beach Brunch Bakehouse (longbeachbrunch), Make Collectives (makecollectives), Kristin Dunn Bookbinding and Design (kdbooks). Optional, defaults to velvetandclay. A common short form works too ("the bakehouse", "the dentist"). A name that does not clearly match one of these is REFUSED with the list, never silently answered about a different business.'}, 'businessId': {'type': 'string', 'description': 'Alias for `business`, accepted because every reply carries this name. Takes a NAME OR AN ID, exactly like `business`. Ignored when `business` is also given.'}}}
biz_menu
Pickup menu and order times
The PICKUP MENU for a business served through this connector, with prices, allergens, how far ahead each item has to be ordered, and the pickup windows available on a date. Call it for an order, a pickup, placing an order, a pickup order, or checkout at a business served here: the menu, the pickup windows and the checkout all come from this one call. No business served here takes pickup orders right now. Pass a date to get that day's pickup windows alongside the menu; omit it for today in the business's own timezone. Item ids from here are what biz_order accepts, exactly as written. PICKUP ONLY: there is no delivery and no shipping. PAYMENT: the ORDER is placed here; paying for it, when the business takes payment, happens on that business's own Square checkout page reached through a sonarconnections.com/p/<code> link, or at the counter on collection. No card data passes through Sonar Connections and this tool has nowhere to put one. A business that does not take pickup orders says so honestly with its opening hours attached. EACH `hoursByDay` ROW CARRIES A `state`: 'open', 'closed', or 'unstated' for a day the business published nothing about. An 'unstated' row reads "hours not listed" and is NEVER spoken as closed; when every day is 'unstated', say the business has not published opening hours and give the phone number. This is a demonstration business and the order book is a sandbox. The business may be given by NAME or by id: "Long Beach Brunch Bakehouse" and "longbeachbrunch" both reach the bakery, and a common short form ("the bakehouse", "the brunch house", "the dentist") works too. A name we cannot place is refused with the list of businesses we do serve, never answered about a different one.
Read only Open world
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'date': {'type': 'string', 'description': 'YYYY-MM-DD, defaults to today in the business timezone. Pickup windows for this date ride along with the menu.'}, 'business': {'type': 'string', 'description': 'Which business, BY NAME OR BY ID. No business served here takes pickup orders right now. A common short form works too ("the bakehouse", "the dentist"). A name that does not clearly match one of these is REFUSED with the list, never silently answered about a different business.'}, 'businessId': {'type': 'string', 'description': 'Alias for `business`, accepted because every reply carries this name. Takes a NAME OR AN ID, exactly like `business`. Ignored when `business` is also given.'}}}
biz_order
Place a pickup order
PLACE a pickup pre-order at a business served through this connector. Call it for checkout: placing an order, placing a pickup order, or confirming an order after biz_menu. Give items (id and qty) from biz_menu, a pickupWindowId from biz_menu, and the FIRST NAME of the person collecting. This tool writes: the order is in the book afterwards and the pickup window is one order fuller. It accepts a first name and an optional short note, and NOTHING ELSE, by design: do not ask the user for a phone number, an email address, a surname or a card, because there is nowhere to put one and the note is scrubbed of contact details server side. This connector never asks for a card and has nowhere to put one. PAYMENT: on most businesses nothing is charged and the order is paid in person at pickup. On a business whose payment lane is on, the result comes back with orderState HELD and a payUrl of the form https://sonarconnections.com/p/<CONFIRMATION_CODE>: the order is NOT placed yet, the pickup window is held for ten minutes, and the order is placed only when that link is paid. GIVE THE USER THE payUrl EXACTLY AS RETURNED and never a link to any other host; it stops working the moment the hold releases, the order is paid or the order is cancelled. PICKUP ONLY, no delivery and no shipping. No business served here takes pickup orders right now. A business that takes no orders returns an honest explanation with its hours instead. An order can be refused for a real reason (an item that is sold out, a quantity outside its limits, a full or past pickup window, or an item that needs more notice than the window gives) and the refusal says which and offers other times. This is a demonstration order book and nothing is reserved in the physical world. The business may be given by NAME or by id: "Long Beach Brunch Bakehouse" and "longbeachbrunch" both reach the bakery, and a common short form ("the bakehouse", "the brunch house", "the dentist") works too. A name we cannot place is refused with the list of businesses we do serve, never answered about a different one.
Open world
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['items', 'pickupWindowId', 'firstName'], 'properties': {'note': {'type': 'string', 'description': 'Optional short preparation note, 140 characters, e.g. "no nuts" or "happy birthday Ada". Contact details are removed server side: this is not a message channel.'}, 'items': {'type': 'array', 'items': {'type': 'object', 'required': ['id', 'qty'], 'properties': {'id': {'type': 'string', 'description': 'An item id from biz_menu, exactly as written'}, 'qty': {'type': 'integer', 'maximum': 9007199254740991, 'minimum': -9007199254740991, 'description': 'How many, within the item minQty/maxQty'}}}, 'description': 'The order lines. At least one.'}, 'business': {'type': 'string', 'description': 'Which business, BY NAME OR BY ID. No business served here takes pickup orders right now. A common short form works too ("the bakehouse", "the dentist"). A name that does not clearly match one of these is REFUSED with the list, never silently answered about a different business.'}, 'firstName': {'type': 'string', 'description': 'First name only. No surname, phone number or email address.'}, 'businessId': {'type': 'string', 'description': 'Alias for `business`, accepted because every reply carries this name. Takes a NAME OR AN ID, exactly like `business`. Ignored when `business` is also given.'}, 'pickupWindowId': {'type': 'string', 'description': 'A window id from biz_menu, e.g. 2026-09-10T10:00'}}}
biz_order_status
Check whether a pickup order is paid
Read the CURRENT state of a pickup order placed through this connector, by its confirmation code (the LBB-XXXXXX style code biz_order returned). It answers with the order state, the payment state, whether it is PAID, the pickup window, the business name and the total, and nothing else: no customer name, no items and no payment link. Use it after a customer has been sent to a checkout page, to tell them whether the payment has landed and the order is placed. It changes nothing. A code that names no order comes back not found.
Read only Open world
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['confirmationCode'], 'properties': {'confirmationCode': {'type': 'string', 'description': 'The order confirmation code, e.g. LBB-KKA8Y2. Case does not matter.'}}}
biz_set_item_availability
Mark a menu item sold out
Mark one item on a business menu as sold out for today, or put it back on. Anyone reading that menu afterwards sees the change, and an order for a sold-out item is refused. TWO CALLS, ALWAYS: call it first with no `confirm` to get a preview of exactly which item will change and what it will read as, plus a `confirmToken`; show that preview to the person; then call it again with confirm true and that token to make the change. The token lasts two minutes, works once, and stops working if any argument changes. It requires a personal connector token: a shared one can read but cannot change anything. Only a business you are seated on as an owner or a manager can be changed, checked against live records every time. Name the item with `itemId` from biz_menu when you have one. `itemName` is accepted and is matched against that menu: a name that fits more than one item is REFUSED with the names it fits, never guessed at, because several items on one menu can share a word.
Open world Idempotent
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['business', 'soldOut'], 'properties': {'itemId': {'type': 'string', 'description': 'The menu item id, exactly as biz_menu returned it. Prefer it whenever you have one: an id can never be ambiguous.'}, 'confirm': {'type': 'boolean', 'description': 'Leave this out on the first call. Pass true with confirmToken to commit.'}, 'soldOut': {'type': 'boolean', 'description': 'true to mark the item sold out for today, false to put it back on the menu.'}, 'business': {'type': 'string', 'description': 'Which business, BY NAME OR BY ID, exactly as biz_menu returned it. Only a business you are seated on can be changed.'}, 'itemName': {'type': 'string', 'description': 'The item by name, when you have no id. Matched against that menu. A name that fits more than one item is refused with the names it fits, never guessed at.'}, 'requestId': {'type': 'string', 'description': 'Your own id for this change, at least 8 characters. Sending the same one twice with the same arguments returns the first result instead of changing anything a second time.'}, 'confirmToken': {'type': 'string', 'description': 'The token the preview returned. Required when confirm is true.'}}}
biz_storefront
Shop catalog, prices and availability
CALL THIS for what a shop sells, its products, its prices, a gift idea, or browsing or shopping a store served here. The SHOP CATALOG for a business served through this connector, read from that shop's OWN published catalog: product titles, the brand or maker, the product type, a price, whether it is in stock, and one image each. Businesses served here: Make Collectives (makecollectives, a boutique and gift shop), Kristin Dunn Bookbinding and Design (kdbooks, a bookbinding and book repair studio). Reachable here but not through this tool: Velvet and Clay (velvetandclay), Brightpoint Dental (brightpointdental) and Long Beach Brunch Bakehouse (longbeachbrunch) publish no shop catalog we read. makecollectives is Make Collectives, a boutique at 430 E. 1st St in Long Beach. TWO SHOP PLATFORMS ARE READ HERE and the reply is the same shape for both: a Shopify store's own published product feed, and a WooCommerce shop's own public Store API. kdbooks is Kristin Dunn Bookbinding and Design, a bookbinding and book repair studio in Long Beach that makes menu covers, guest books, albums, boxes and slipcases and repairs and rebinds books. Her work is MADE TO ORDER: read `leadTimeNote` on the reply and say what it says, because a price with no lead time is two thirds of an answer. ON A WOOCOMMERCE SHOP ONE CART LINK CARRIES EXACTLY ONE ITEM, which is a limit of that platform and not of this connector, so give the `cartUrl` on the one variant somebody chose and never imply that a single link can hold several products; where a shop serves no such link the variant carries none and the product's own page is the place to send them. `storefrontKind` on the reply says which platform answered. Pass `query` to narrow it to what somebody asked for ("rings", "books"); it only ever REMOVES products and never reorders them, because nothing in this connector is paid placement. The catalog is PAGED: sixty products come back per call and the reply carries `page`, `pageCount` and `total`, so a shop with 340 products is six pages and not sixty products. Pass `page` (1-based) to read the rest; never tell somebody sixty is all this shop has, because it is not. `query` searches the WHOLE catalog and not just the first page, so "candles" finds her candles wherever they sit in it. PASS THE PERSON'S OWN WORDS: every word you pass must match the start of some word in a product's title, brand, type or handle, singulars and plurals find each other and word order does not matter, so "amazonite rings", "amazonite ring" and "rings" all reach the same ring. A `page` past the end answers with no products and the real `pageCount`, which is the number to ask again with. BUYING HAPPENS ON THE SHOP'S OWN SITE: each purchasable variant carries a `cartUrl` that is the shop's own cart link, and opening it lands on THEIR checkout. Give that url exactly as returned and never a link to any other host. WHERE THIS REPLY DRAWS THE SHOP CARD, THE CARD ITSELF HOLDS A BASKET: the person taps a product on the card and taps Add to cart, and the card's own Check out opens the shop's own checkout with those items already on it, so never tell somebody you cannot put something in a basket. WHERE THE REPLY CARRIES shopUrl, that is this WHOLE SHOP as a page somebody can open in an ordinary browser, drawn with the same card and carrying the same basket and the same checkout, so offer that url exactly as returned and never compose one of your own. Read `buyingNote` on the reply, which says which of those two is true for this serve, and say what it says. No payment passes through Sonar Connections, this tool cannot take a payment, and no fee is added to the shopper. This connector does NOT hold this shop's stock levels, its opening hours or its order book: say what the catalog says and send people to the shop for anything else. A business that publishes no catalog we read says so honestly with its own website attached. The business may be given by NAME or by id: "Long Beach Brunch Bakehouse" and "longbeachbrunch" both reach the bakery, and a common short form ("the bakehouse", "the dentist") works too. A name we cannot place is refused with the list of businesses we do serve, never answered about a different one.
Read only Open world
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'page': {'type': 'integer', 'maximum': 9007199254740991, 'minimum': -9007199254740991, 'description': 'Which page of the catalog, 1-based. Optional, defaults to 1. Each page holds up to 60 products; the reply carries pageCount and total so you can say which page you are reading and ask for the next one. A page past the end answers with no products and the true pageCount rather than an error.'}, 'limit': {'type': 'integer', 'maximum': 9007199254740991, 'minimum': -9007199254740991, 'description': 'How many products to return, 1 to 60. Optional, defaults to 60. A larger number is clamped rather than refused.'}, 'query': {'type': 'string', 'description': 'Free text to narrow the catalog to, matched against the product title, the brand, the product type and the handle. Optional; omit it for the whole shop. It only ever removes products and never reorders them.'}, 'business': {'type': 'string', 'description': 'Which business, BY NAME OR BY ID. Available: Make Collectives (makecollectives), Kristin Dunn Bookbinding and Design (kdbooks). The default (velvetandclay) publishes no shop catalog we read, so NAME THE BUSINESS: an omitted argument is refused. A common short form works too ("the bakehouse", "the dentist"). A name that does not clearly match one of these is REFUSED with the list, never silently answered about a different business.'}, 'businessId': {'type': 'string', 'description': 'Alias for `business`, accepted because every reply carries this name. Takes a NAME OR AN ID, exactly like `business`. Ignored when `business` is also given.'}}}
booth_set_away
Set a booth as stepped away
Mark a booth you staff as stepped away, or back. Attendees looking at that booth see the presence state change. TWO CALLS, ALWAYS: call it first with no `confirm` to get a preview of exactly what will change plus a `confirmToken`, show that preview to the person, then call it again with confirm true and that token to make the change. The token lasts two minutes, works once, and stops working if any argument changes. It requires a personal connector token: a shared one can read but cannot change anything. Only a booth you own, administer or staff at that event can be changed, checked against live records every time.
Idempotent
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['eventId', 'boothId', 'away'], 'properties': {'away': {'type': 'boolean', 'description': 'true to mark the booth stepped away, false to mark it back.'}, 'boothId': {'type': 'string', 'description': 'The booth id, exactly as events_booths returned it. Not the booth name.'}, 'confirm': {'type': 'boolean', 'description': 'Leave this out on the first call. Pass true with confirmToken to commit.'}, 'eventId': {'type': 'string', 'description': 'The event the booth is at, exactly as events_list returned it.'}, 'requestId': {'type': 'string', 'description': 'Your own id for this change, at least 8 characters. Sending the same one twice with the same arguments returns the first result instead of changing anything a second time.'}, 'confirmToken': {'type': 'string', 'description': 'The token the preview returned. Required when confirm is true.'}}}
city_calendar
Public events calendar
Upcoming public events run by the City of Long Beach: library programmes, parks and recreation, animal care clinics, city clerk and council sessions, hazardous waste collection, economic development workshops and more. Read from the calendar publisher's own JSON feed rather than scraped from a page, and every response says so. Every response names the City of Long Beach as its source and carries the license state in the City's own terms. Times are returned exactly as the City publishes them, as local wall-clock strings with the UTC offset beside them, and are never converted. Cancelled events are RETURNED and clearly marked rather than hidden, because a cancelled event is the answer to "is it on tonight". Coverage today: the City of Long Beach public events calendar, one publisher.
Read only Open world
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'days': {'type': 'number', 'description': 'How many days ahead to read, 1 to 60 (default 14)'}, 'limit': {'type': 'number', 'description': 'Events to return, 1 to 50 (default 10)'}, 'search': {'type': 'string', 'description': 'Match a word across event title, description, location and department'}, 'department': {'type': 'string', 'description': 'Filter by city department or calendar, e.g. "Long Beach Public Library"'}}}
city_datasets
List public open datasets
The open data catalog of one public data source: every dataset with its id, title, description, record count, last-modified date and license. Call this first to discover which dataset ids city_records accepts. `source` is optional and defaults to "longbeach" (the City of Long Beach portal, DataLB). Every response names its source.
Read only Open world
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'source': {'type': 'string', 'description': 'Data source id, e.g. "longbeach" (default)'}}}
city_gis
City GIS layers
Search and read a city GIS, a public ArcGIS organization of map layers covering parcels, zoning, districts, bikeways, parks, neighborhoods, permits and more. SOURCES: `longbeach` (City of Long Beach, 174 public layers listed) and `huntingtonbeach` (City of Huntington Beach, 113 servable of 121 listed; the other 8 are hosted on the City's own server, which this connector does not read). Pass `source` to choose; it defaults to longbeach. Each answer names the city it came from, and a search answer says how many results it refused and why. Every layer is read live from the publisher's own published ArcGIS organization, and every response names that publisher as its source and carries the license state in the publisher's own terms. HOW TO USE IT: call with `search` to find layers by topic and get their item ids, then call with `item_id` AND THE SAME `source` to read one layer. Reading a layer returns its field schema, its row count and a capped sample of rows; add `filter` to match a word across the layer's text fields. WHAT IT WILL NOT DO: it never returns raw geometry, so a polygon layer answers which, where and how many rather than emitting coordinates. Any layer whose field names look like they describe individual people (owner or applicant names, home addresses, plates, dates of birth), and any Survey123 response layer whatever its columns are called, returns its schema and counts only, never rows, and says what triggered that. The screen is conservative and can fire on a layer that only describes places, which is why it reports its reasons. Coverage today: two city GIS organizations, the City of Long Beach and the City of Huntington Beach.
Read only Open world
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'layer': {'type': 'number', 'description': 'Layer index within the service (default 0)'}, 'limit': {'type': 'number', 'description': 'Results to return, 1 to 50 (default 10)'}, 'filter': {'type': 'string', 'description': 'Match a word across the layer text fields, e.g. a street or a name'}, 'search': {'type': 'string', 'description': 'Find layers by topic, e.g. "zoning", "parks", "bike"'}, 'source': {'type': 'string', 'description': 'Which city GIS: "longbeach" or "huntingtonbeach" (default longbeach)'}, 'item_id': {'type': 'string', 'description': 'ArcGIS item id from a search result, to read that layer'}}}
city_records
Read records from a public open dataset
Read one PAGE of records from a public open dataset. Give a dataset_id from city_datasets, an optional full-text search, an optional limit (default 10, maximum 50) and an optional offset to page through larger result sets. Datasets can hold hundreds of thousands of records, so a full page is usually NOT the whole answer: the response carries `truncated`, `matchingRecords` and a `nextOffset` to call back with. `source` is optional and defaults to "longbeach" (the City of Long Beach portal, DataLB). Returns the dataset schema plus the records, and names its source.
Read only Open world
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['dataset_id'], 'properties': {'limit': {'type': 'number', 'description': 'Rows to return, 1 to 50 (default 10)'}, 'offset': {'type': 'number', 'description': 'Rows to skip, for paging. Use the `nextOffset` from a previous call. 0 to 1000; deeper paging is not served (download the full file from the city portal instead).'}, 'search': {'type': 'string', 'description': 'Optional full-text search across the records'}, 'source': {'type': 'string', 'description': 'Data source id, e.g. "longbeach" (default)'}, 'dataset_id': {'type': 'string', 'description': 'Dataset id from city_datasets, e.g. "service-requests"'}}}
city_sweeping
Street sweeping schedule
Street sweeping schedules for the City of Long Beach, read live from the City of Long Beach GIS (a public ArcGIS feature service), which is the City's own published open data. Every response names the City of Long Beach as its source and carries the license state in the City's own terms. WHAT THE DATA ACTUALLY IS: 336 schedule POLYGONS whose only attributes are DAYS (e.g. "Tuesday/Wednesday", "Friday") and HOUR (e.g. "8-10a", "1230-230p"). There is no street name, no street side, and no route or week number in the layer, so a `street` lookup is answered by intersecting the City's own street centerlines with the zone polygons, and the answer names the zones a street runs through rather than one schedule per address. Two-day values are reported as published: the City does not state whether they mean both days or one side of the street per day, and this tool will not guess. Call with `street`, with `day`, with both, or with neither to see every schedule the City publishes. Every response names its source and its license state. Coverage today: street sweeping in the City of Long Beach, one publisher.
Read only Open world
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'day': {'type': 'string', 'description': 'Day filter, e.g. "Tuesday". The published data covers Monday to Friday only.'}, 'limit': {'type': 'number', 'description': 'Distinct schedules to return, 1 to 25 (default 10)'}, 'street': {'type': 'string', 'description': 'Long Beach street name, e.g. "Pine Ave" or "East Ocean Blvd". Resolved against the City street centerline layer.'}}}
event_accept
Accept a hello
Accept a hello the person has received, which opens a conversation with that person. Use it for "accept Dana", "yes, connect me with Jo", "say yes to her". Name the hello with `firstName` exactly as an event_requests row spelled it, or with that row's `requestId`; never invent either. CONFIRM FIRST: say whose hello you are accepting and get a yes. A `firstName` that matches two waiting hellos comes back AMBIGUOUS_NAME and accepts nothing, and you ask which one they mean. It accepts only hellos addressed to the caller: the server re-checks that and refuses with NOT_RECEIVER otherwise. Accepting twice is harmless. On ok:true say the conversation is open and that they can read and reply with event_inbox and event_reply; do not say anything about what the other person will do. It requires a personal connector token.
Idempotent
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'firstName': {'type': 'string', 'description': "OPTIONAL. The FIRST NAME exactly as an event_requests row spelled it. Matched against the caller's OWN pending hellos only. Two matches come back AMBIGUOUS_NAME and NOTHING IS ACCEPTED, and you ask which one they mean."}, 'requestId': {'type': 'string', 'description': 'OPTIONAL. The requestId exactly as an event_requests row gave it. Never construct one. Pass this OR firstName; passing both uses this one.'}}}
event_find_matches
Find matching attendees
The people at an event the person is at whose stated intent fits theirs. Use it for "who should I meet", "who here is looking for investors", "who is checked in that matches what I am here for", "any buyers on the floor". Each row carries a first name, their intent, the one line they wrote about what they are looking for, and the booth they staff when they are a vendor. It carries no phone number, no email address, no surname, no account id and no photo: those are not on this surface. It answers only about people who finished a badge at that event and chose to be findable by other attendees, and it returns at most 20 of them, so a longer floor comes back as the first 20 with `truncated` true. Rows are RANKED by what each person actually WROTE on their badge, not only by their category: the server scores the one line and the interests they declared against the caller's own, and each row carries `fit` and `why`. `fit` IS ONE OF THREE WORDS and it is the whole of what the strength of a match may be called: "strong" means most of what the caller declared is echoed on the other side, "good" means a real overlap worth walking over for, and "some" means they are on the list for a reason and no more than that. `why` is one sentence composed by the server: it OPENS with that same fit and then names the words the two of them share and how the categories relate. When they share no word at all the `why` names the TOPIC they both wrote about instead, from the server's own list of topics, so a person who wrote about swimming pools and a person who wrote about pool accessories are told they both wrote about pools. READ THE `fit` AND THE `why` OUT, exactly as the row gives them, and never invent a different reason, and never guess a topic the `why` did not name. SAY ONLY WHAT THIS REPLY CARRIES: do not add how to find a person, whether the list is complete, who else might be there, what will happen next or why somebody is or is not on it, because every one of those is a guess about a floor this reply does not describe. Two buyers whose lines agree ARE matches for each other; a buyer and a vendor with nothing written still surface, because the complementary pair (buyers with vendors and networkers, vendors with buyers and networkers) counts toward the ranking. THERE IS NO NUMBER ON THIS SURFACE, and none may be supplied for it: never state a score, a percentage, a rating out of anything, a rank or a place in the list for anybody, and never turn a fit word back into one. The rows are already ordered, best fit first, which is all the ordering anyone needs to be told. If the person has not said what they are there for it comes back with `needsIntent` true and no rows: call event_set_intent first. Reading this list does not require being findable oneself, and the reply says which the caller is. WHEN IT COMES BACK EMPTY IT SAYS WHY, and the reason is the server's rather than yours: a reply with no rows carries `emptyReason`, one of four words, and a `message` that states it in plain language. STATE THAT REASON AS GIVEN AND NEVER SUBSTITUTE ONE OF YOUR OWN. `none_findable` means nobody else at that event has chosen to be findable by other attendees. `none_present` means people there are findable but none of their badges has been set or updated inside the event's own window, so none of them counts as being there. `event_not_live` means the event is not inside its own dates right now and no badge was set inside them. `no_text_match` means there are people there but none of them is close enough to what this person said they are there for. Do not infer a reason the reply does not give: not the dates, not who has arrived, not travel, not timing.
Read only
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'eventId': {'type': 'string', 'description': 'OPTIONAL. Omit for the event the person is currently in, which is the usual case. Only pass one if they named a different show, and it must be one they have already joined.'}}}
event_inbox
Read my messages
The person's own conversations with people they have connected with at an event, and the last few lines of one of them. Use it for "any messages", "did Jo reply", "what did Dana say", "read my inbox". Called with no arguments it lists up to twenty threads, person-to-person ones first: each row carries the other person's FIRST NAME, the last line, when it landed, whether that line was the person's own, and how many they have not read. Called with `firstName` or `chatId` it returns the last few lines of that one conversation, oldest first, each line saying only whether it was theirs, what it said and when. It carries no phone number, no email address, no surname, no account id and no photo: those are not on this surface. IT READS ONLY THE CALLER'S OWN CONVERSATIONS and the server re-checks that on every call, so a conversation they are not in comes back refused with NOT_PARTICIPANT rather than empty. A `firstName` is matched against THEIR OWN THREADS ONLY: if two of them answer to it the reply is AMBIGUOUS_NAME and names neither, and you ask which one they mean rather than choosing. If none does it is NAME_NOT_IN_THREADS, and you say you cannot see a conversation with that person. SHOW FIRST NAMES AND READ THE LINES OUT AS GIVEN. Say only what the reply carries: never guess who somebody is, what they meant, whether they are still at the event, or what is in a thread this reply did not return. Reading a conversation MARKS IT READ for that person, exactly as opening it in the app or on the web does. It requires a personal connector token: a shared one cannot reach anybody's conversations at all.
Read only Idempotent
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'limit': {'type': 'number', 'maximum': 50, 'description': 'OPTIONAL. How many lines of one conversation to return, at most 50. Omit for the last 30. Ignored when listing threads, which is always at most 20.'}, 'chatId': {'type': 'string', 'description': 'OPTIONAL. The id of one conversation, exactly as a thread row from this same tool gave it. Never construct one. Pass this OR firstName, not both; passing both uses this one.'}, 'firstName': {'type': 'string', 'description': "OPTIONAL. The FIRST NAME of the person whose conversation to read, exactly as a thread row spelled it. Matched against the caller's OWN conversations only. If two of them answer to it the reply is AMBIGUOUS_NAME and nothing is read, and you ask which one they mean rather than choosing."}}}
event_redeem_code
Redeem an event code
Join an event with a code the person was given, on a badge, a poster, an email or at a door. THE CODE IS THE ONLY THING TO PASS: it names its own event, so never ask which event a code is for and never ask for an event id. TWO CALLS, ALWAYS: call it first with no `confirm` to get back the event the code opens and the seat it gives plus a `confirmToken`, show that to the person, then call it again with confirm true and that token to take the seat. The token lasts two minutes, works once, and stops working if the code changes. It requires a personal connector token: a shared one can read but cannot change anything. Redeeming works from anywhere, not only at the venue.
Idempotent
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['code'], 'properties': {'code': {'type': 'string', 'description': 'The code exactly as the person said or read it. Case, spaces and dashes are normalized, so "tie-24" and "TIE24" are the same code.'}, 'confirm': {'type': 'boolean', 'description': 'Leave this out on the first call. Pass true with confirmToken to commit.'}, 'requestId': {'type': 'string', 'description': 'Your own id for this redemption, at least 8 characters. Sending the same one twice with the same code returns the first result instead of redeeming a second time.'}, 'confirmToken': {'type': 'string', 'description': 'The token the preview returned. Required when confirm is true.'}}}
event_reply
Reply to a message
Send one message into a conversation the person already has with somebody they connected with at an event. Use it for "reply to Dana", "tell Jo I am on my way", "answer her". Name the conversation with `firstName`, exactly as event_inbox spelled it, or with the `chatId` event_inbox returned; never invent either, and never send to a name you have not read off a thread. `text` is the PERSON'S OWN WORDS: send what they said and do not tidy it, shorten it or improve it. CONFIRM BEFORE SENDING, ALWAYS: show the person the message and the first name it is going to and get a yes, because the message is delivered the moment this returns and nothing can unsend it. If they have not said what to send, ask them - never write a message on somebody's behalf. It sends as that person, into their own conversation, and it can reach nobody they are not already talking to: the server re-checks that on every call and refuses with NOT_PARTICIPANT otherwise. A `firstName` that matches two of their conversations comes back AMBIGUOUS_NAME and sends nothing, and you ask which one they mean. The same cooldown, flood limit and content rules the app's own send has apply here, because it is the same send: RATE_LIMITED means they are sending too fast and should wait a moment. On ok:true say it was sent and nothing more - do not promise a reply, do not say when one will come, and do not claim the other person has read it. It requires a personal connector token: a shared one can read nothing here and can send nothing.
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['text'], 'properties': {'text': {'type': 'string', 'maxLength': 1000, 'description': "REQUIRED. The message, in the PERSON'S OWN WORDS, up to 1000 characters. Send what they said: do not tidy it, do not shorten it, do not improve it and never invent one. If they have not said what to send, ask them instead of calling this."}, 'chatId': {'type': 'string', 'description': 'OPTIONAL. The id of the conversation to send into, exactly as an event_inbox thread row gave it. Never construct one. Pass this OR firstName, not both; passing both uses this one.'}, 'firstName': {'type': 'string', 'description': "OPTIONAL. The FIRST NAME of the person to answer, exactly as an event_inbox thread row spelled it. Matched against the caller's OWN conversations only. Two matches come back AMBIGUOUS_NAME and NOTHING IS SENT, and you ask which one they mean rather than choosing: there is no way to unsend a message to the wrong person."}}}
event_requests
Who wants to meet me
Who wants to meet the person: the hellos waiting on them at an event, newest first. Use it for "who wants to meet me", "any requests", "did anyone say hello". Each row carries the other person's FIRST NAME, their here-for line in their own words, and when the hello landed, plus a requestId to accept it with. It carries no phone number, no email address, no surname, no account id and no photo. It reads only the CALLER'S OWN pending hellos. Name people by the first name on the row and read the here-for line as given; never guess who somebody is or why they said hello. To accept one, confirm the first name with the person and call event_accept. It requires a personal connector token.
Read only Idempotent
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {}}
event_say_hello
Say hello
Say hello to somebody the person has been shown in their event matches: it sends that person a connection request from them, and when it is accepted a conversation opens that both can read and answer from the app, the web page or an assistant. Use it for "say hello to Jo", "introduce me to her", "how do I message him". Pass the FIRST NAME exactly as an event_find_matches row spelled it and nothing else: there is no account id on this surface and you must never invent one. The person must be in their CURRENT MATCH POOL and the server re-checks that on every call. CONFIRM FIRST: say who the hello is going to and get a yes, because it reaches another person. Reasons to read out as given: "not_in_pool" means you cannot see them in their matches, so offer to list them again; "ambiguous" means two people there answer to that name, so ask which one and never pick; "already_sent" means the hello is already out; "no_seat" means they are not seated at an event; "rate_limited" means they have said hello to a lot of people today. On success say the reply's own `message` and nothing more: do not promise they will accept, do not say when, and do not claim a conversation is open. It requires a personal connector token.
Idempotent
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['firstName'], 'properties': {'firstName': {'type': 'string', 'maxLength': 40, 'description': 'REQUIRED. The FIRST NAME of the person, exactly as an event_find_matches row spelled it. Never a surname, never an account id, never a name the person has not been shown on a row. If two people in their matches answer to it the reply is `ambiguous` and nothing is sent, and you ask which one they mean.'}}}
events_booth_detail
Get one booth card
The full public card for one booth: description, menu items with ticket prices where present, `products` (what the vendor sells, as the booth sheet in the app lists it), the printed aisle, public links, logo and today's offering if set. `mapless: true` means the booth has no position on the floor plan. Accepts a booth id or a booth/vendor name.
Read only
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['eventIdOrSlug', 'boothNameOrId'], 'properties': {'boothNameOrId': {'type': 'string', 'description': 'Booth id (stall_frosted_cupcakery) or name'}, 'eventIdOrSlug': {'type': 'string', 'description': 'Event id (belmont_stroll), public slug (cba26), or the event NAME as events_list spells it ("Summer Stroll & Savor"). Common short forms work too ("the stroll", "tie summit").'}}}
events_booths
List booths and vendors
Booths and vendors at an event: name, category, booth number, the printed aisle where the floor has them ("Water Side"), and a short blurb. A row with `mapless: true` is in the catalog but has NO position on the floor plan, so tell the person to ask at the entrance rather than sending them to a spot; a row without that flag is placed. Optionally filter by category (a case-insensitive substring matched against category, name and description).
Read only
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['eventIdOrSlug'], 'properties': {'category': {'type': 'string', 'description': 'Optional category filter, e.g. "dessert"'}, 'eventIdOrSlug': {'type': 'string', 'description': 'Event id (belmont_stroll), public slug (cba26), or the event NAME as events_list spells it ("Summer Stroll & Savor"). Common short forms work too ("the stroll", "tie summit").'}}}
event_set_intent
Set an event intent
Set what the person is at an event for, and whether other attendees there may find them. Use it for "set my intent", "I am here to buy", "tell people I am looking for investors", "make me findable". ASK TWO QUESTIONS AND PASS BOTH ANSWERS IN THEIR OWN WORDS: "What are you here for?" is `headline`, and "Who do you want to meet?" is `lookingFor`. THOSE TWO SENTENCES ARE THE BADGE. Together with their name they are the whole of what makes a person findable at this event, and they are what the matcher reads to decide who they are shown to, so ask both, pass both, and do not compress them, tidy them or invent them. `intent` is OPTIONAL and is a quick pick rather than a question you owe: pass one of Buyer, Vendor, Networker or Social only when the person actually said one of those words, and otherwise leave it out, because the server works the category out from what they wrote and falls back to Networker exactly as their badge in the app does. IF THEY NAME A CATEGORY OF THEIR OWN - "investor", "director", anything - pass it as `label` and it is kept as their word rather than refused; never talk them out of it and never map it onto one of the four yourself. `discoverable` is a SEPARATE and REQUIRED answer and is never inferred from the intent: ask the person, because true puts them in the list other attendees can see and false keeps them out of it. TWO CALLS, ALWAYS: call it first with no `confirm` to get back a sentence saying exactly what will change plus a `confirmToken`, show that sentence to the person, then call it again with confirm true and that token. The token lasts two minutes, works once, and stops working if any argument changes. It requires a personal connector token: a shared one can read but cannot change anything. It changes that one person's badge at one event and reaches nobody else's. A badge with one of the two sentences still blank cannot be found by anybody yet, so it is refused naming the sentence that is missing rather than written. CLOUD 181a: `firstName` IS THE THIRD THING THE BADGE IS MADE OF, beside the two sentences above, and it is OPTIONAL in the same way they are. Pass it when the person has just told you their name or asked to change it and leave it out every other time: an omitted name leaves theirs alone and an invented one would rename them. Until this unit there was no door onto that field outside the app, which is why a person who had only ever used an assistant or a browser could not finish a badge however many sentences they wrote. A name the badge cannot take refuses the whole call rather than writing half of it, and the refusal says which thing was wrong with it.
Idempotent
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['discoverable'], 'properties': {'label': {'type': 'string', 'maxLength': 24, 'description': 'OPTIONAL. Their own word for what they are, when none of the four fits: "Investor", "Director", "Press". Up to 24 characters, letters, spaces and hyphens only. It is KEPT AND SHOWN as their word and is never refused for being outside the four; the server still files one of the four behind it so the match list can say why two people fit. Pass it only when the person named it themselves - it is a fact about them, so never invent one and never tidy theirs.'}, 'intent': {'type': 'string', 'description': 'OPTIONAL quick pick, not a question you have to ask. One of Buyer, Vendor, Networker or Social, as the person said it; case and surrounding spaces do not matter. Leave it out when they did not name one of those four words: the server derives the category from the two sentences and falls back to Networker, which is what their badge in the app does. A word outside the four does NOT go here - it goes in `label`, where it is kept rather than refused.'}, 'confirm': {'type': 'boolean', 'description': 'Leave this out on the first call. Pass true with confirmToken to commit.'}, 'eventId': {'type': 'string', 'description': 'OPTIONAL. Omit for the event the person is currently in, which is the usual case. Only pass one if they named a different show, and it must be one they have already joined.'}, 'headline': {'type': 'string', 'maxLength': 280, 'description': 'What they are here for, in their OWN words, up to 280 characters. This is the first of the two sentences the badge is made of, so ask "What are you here for?" and pass what they say. FULL SENTENCES ARE THE POINT: it is read by the matcher that decides who they are shown to and it is what strangers read about them, so "raising a seed round for a logistics startup" beats "raising money". Phone numbers, email addresses and links are removed on the server, because other attendees read it. Leaving it out keeps whatever their badge already says and never clears it.'}, 'firstName': {'type': 'string', 'maxLength': 40, 'description': "OPTIONAL. The person's FIRST NAME, 2 to 40 characters of letters, spaces, hyphens and apostrophes. It is the THIRD thing a badge is made of, beside the two sentences: a badge with no name cannot be found by other attendees either. Pass it only when they have just told you their name or asked to change it; leaving it out keeps whatever their badge already says and never clears it. Never invent a name, never shorten one they gave you, and never pass a surname."}, 'requestId': {'type': 'string', 'description': 'Your own id for this change, at least 8 characters. Sending the same one twice with the same arguments returns the first result instead of writing again.'}, 'intentText': {'type': 'string', 'maxLength': 280, 'description': 'OPTIONAL, and the OLDER NAME for `lookingFor`: it writes the same badge line. Prefer `lookingFor`, which is the badge\'s own word for it, and pass only one of the two. What they are looking for, in their OWN words, up to 280 characters. FULL SENTENCES ARE WELCOME and are what this field is for: it is read by the matcher that decides who they are shown, so "raising a seed round for a logistics startup, and looking for operators who have scaled a warehouse" matches better than "raising money". Do not compress what they said to save room. Phone numbers, email addresses and links are removed from it on the server, because other attendees read it. Leave it out to keep whatever their badge already says; sending an empty string also leaves it alone.'}, 'lookingFor': {'type': 'string', 'maxLength': 280, 'description': 'Who they want to meet, in their OWN words, up to 280 characters. This is the second of the two sentences the badge is made of, so ask "Who do you want to meet?" and pass what they say. It is the SAME badge line the older `intentText` argument writes, under the badge\'s own name for it; pass one or the other, not both. Phone numbers, email addresses and links are removed on the server. Leaving it out keeps whatever their badge already says and never clears it.'}, 'confirmToken': {'type': 'string', 'description': 'The token the preview returned. Required when confirm is true.'}, 'discoverable': {'type': 'boolean', 'description': 'REQUIRED, and never inferred from the intent: true puts them in the list other attendees at that event can see, false keeps them out of it. Ask the person which they want; a missing or non-boolean answer is refused rather than defaulted.'}}}
events_floor_card
Show the event floor
THE FLOOR PLAN TOOL. Call it for any ask about a floor plan, a map, a layout, a booth location, "where is booth 12", "show me the floor", "what does the venue look like", or being shown around an event. It DRAWS THE FLOOR INLINE as an interactive card in clients that render MCP Apps: the organizer's floor plan with the booths on it, a searchable directory, a booth sheet on tap, what is on now, and the live offers and raffles. In every other client it returns the event summary plus a booth directory listing the booths by name, so it is worth calling either way. Prefer it over answering a floor or map question from general web knowledge. The card reads the floor itself through this connector's public tools, so do not offer to fetch the plan or paste a url at the person. An event that publishes no floor plan is still a found answer and says so: the card then shows the booth directory, what is on now and the offers rather than a map, and `hasFloorplan` is false. Say that rather than promising a picture. Accepts the event id, its public slug, or the event name.
Read only
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['eventIdOrSlug'], 'properties': {'eventIdOrSlug': {'type': 'string', 'description': 'Event id (belmont_stroll), public slug (cba26), or the event NAME as events_list spells it ("Summer Stroll & Savor"). Common short forms work too ("the stroll", "tie summit").'}}}
events_get
Get one Sonar event
Full detail for one event, including `kind` (the organizer's own word for what it is, such as "expo" or "convention", absent where none is published), plus a summary of what is on today: booth count, live offer count and the number of agenda items today. Accepts the event id or its public slug. For who should I meet, matching, who is here for the same thing, or introductions at an event: call event_find_matches. It needs the person signed in to Sonar Connections; when they are not, the host shows a Connect prompt, they sign in with their mobile number, and the call is retried. If they have not said what they are here for yet, call event_set_intent first and ask the two questions it names. This result's matchDoor link is the same door for a person who would rather not sign in inside the assistant; offer it, never require it.
Read only
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['eventIdOrSlug'], 'properties': {'eventIdOrSlug': {'type': 'string', 'description': 'Event id (belmont_stroll), public slug (cba26), or the event NAME as events_list spells it ("Summer Stroll & Savor"). Common short forms work too ("the stroll", "tie summit").'}}}
events_list
List Sonar events
List the Sonar Connections events available through this connector: id, slug, name, venue or city, dates, description and `kind` (the organizer's own word for what it is, such as "expo" or "convention"; absent on events that publish none, and never guess one). Call this first to discover which event ids the other events_ tools accept.
Read only
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {}}
events_offers
List live offers
Live and scheduled public offers at an event: title, which booth, the time window in minutes and remaining-count style numbers.
Read only
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['eventIdOrSlug'], 'properties': {'eventIdOrSlug': {'type': 'string', 'description': 'Event id (belmont_stroll), public slug (cba26), or the event NAME as events_list spells it ("Summer Stroll & Savor"). Common short forms work too ("the stroll", "tie summit").'}}}
events_seat_bundle
Open an event in one call
EVERYTHING ABOUT ONE EVENT IN A SINGLE CALL, for a client that is drawing a whole page and would otherwise make five round trips: the event summary, the booth count with the first page of booths, the programme, the live offers and raffles, and `hasFloorplan`. Built for the web event door at sonarconnections.com/e/<eventId>, and useful to any caller that wants the whole picture at once rather than one section. `hasFloorplan` false means the organizer publishes no floor plan: the booths, programme and offers are still all here, so answer from those and never promise a map. Each block says whether there is `more` and which tool to page it with. IF YOU ONLY WANT ONE SECTION, call that section's own tool instead (events_get, events_booths, events_whats_on, events_offers): they are cheaper and they are unchanged. Accepts the event id, its public slug, or the event name. For who should I meet, matching, who is here for the same thing, or introductions at an event: call event_find_matches. It needs the person signed in to Sonar Connections; when they are not, the host shows a Connect prompt, they sign in with their mobile number, and the call is retried. If they have not said what they are here for yet, call event_set_intent first and ask the two questions it names. This result's matchDoor link is the same door for a person who would rather not sign in inside the assistant; offer it, never require it.
Read only
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['eventIdOrSlug'], 'properties': {'eventIdOrSlug': {'type': 'string', 'description': 'Event id (belmont_stroll), public slug (cba26), or the event NAME as events_list spells it ("Summer Stroll & Savor"). Common short forms work too ("the stroll", "tie summit").'}}}
events_speaker_detail
Get one speaker
Everything an event publishes about one person on its programme: their job title line, `role` (a speaker-level note such as "Moderator"), company, bio, expertise tags, public social links, a portrait, a link to the organizer's own profile page, and every session they are on with the spoken local time. Accepts a name or a speakerId. If the name is not clear enough to be sure - two people sharing a surname, say - the reply is a not-found carrying the closest names rather than a guess, so ask the person which one they meant. Absent fields are null: the organizer published nothing there, so say nothing rather than filling the gap.
Read only
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['eventIdOrSlug', 'speaker'], 'properties': {'speaker': {'type': 'string', 'description': 'A speaker name ("Aasif Mandvi", or just a surname) or a speakerId as events_speakers returns it'}, 'eventIdOrSlug': {'type': 'string', 'description': 'Event id (belmont_stroll), public slug (cba26), or the event NAME as events_list spells it ("Summer Stroll & Savor"). Common short forms work too ("the stroll", "tie summit").'}}}
events_speakers
List an event's speakers
The people on an event's programme: name, their job title line, `role` (what the organizer published for that PERSON, such as "Moderator" or "Judge" - it is a speaker-level note, so do not read it as "the moderator of this one session"), a portrait photo URL, a link to the organizer's own profile page, and the sessions they are on with the spoken local time. Ordered by when they are first on stage. Optionally filter to one day. Any field except the name may be null, which means the organizer published nothing there: say nothing rather than filling the gap. When an event publishes no speaker records the roster is built from the programme itself and `source` says "program"; those rows carry a `kind` of "speaker" or "performer" and nothing else about the person.
Read only
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['eventIdOrSlug'], 'properties': {'day': {'type': 'string', 'description': 'Optional day filter: "today" or YYYY-MM-DD, read in the event\'s own timezone'}, 'eventIdOrSlug': {'type': 'string', 'description': 'Event id (belmont_stroll), public slug (cba26), or the event NAME as events_list spells it ("Summer Stroll & Savor"). Common short forms work too ("the stroll", "tie summit").'}}}
events_whats_on
Get the agenda or lineup
Agenda sessions and performances with their times. `when` accepts "all" (default), "today", "now" (the next few hours) or a YYYY-MM-DD date. Each row carries a `speakers` array in the order the session lists them, with each speaker's name, `role` (what the organizer published for that PERSON - "Moderator", "Judge" - it is a speaker-level note, so do not read it as "the moderator of this one session"), `title` (their job title line, which is a different fact from role and both may be present), `company`, `bio`, `expertiseTags`, `socialLinks`, a portrait photo URL, and a link to the organizer's own speaker profile page. Any of these except the name may be null or absent, which means the organizer did not publish it: say nothing rather than filling the gap. `speakerNames` is still there for the plain lineup.
Read only
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['eventIdOrSlug'], 'properties': {'when': {'type': 'string', 'description': '"all" | "today" | "now" | YYYY-MM-DD'}, 'eventIdOrSlug': {'type': 'string', 'description': 'Event id (belmont_stroll), public slug (cba26), or the event NAME as events_list spells it ("Summer Stroll & Savor"). Common short forms work too ("the stroll", "tie summit").'}}}
ui_card_diag
Card diagnostics sink
INTERNAL. The diagnostics sink for the interactive cards this connector serves. A card view posts its own lifecycle markers here in small batches: that it mounted, which display mode and safe-area insets the host gave it, the heights it reported, whether a keyboard opened, and the outcome of the one action a person took on it. It accepts a closed vocabulary of markers and integer counts only, no free text of any kind, and it returns nothing but an acknowledgement. NOT FOR A MODEL TO CALL: it answers no question and looks nothing up. Call a data tool instead.
Idempotent
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['card', 'sessionKey', 'seq', 'events'], 'properties': {'seq': {'type': 'number', 'description': 'Which batch this is for that mount, 1 to 6. Past the budget it is refused.'}, 'card': {'type': 'string', 'description': 'Which card is speaking: menu, order, floor or storefront.'}, 'host': {'type': 'string', 'description': 'Which surface drew this card when it is not an MCP host: "standalone" for the connector\'s own shop page. Omit it inside a host. Any other value refuses the batch.'}, 'events': {'type': 'array', 'items': {'type': 'object', 'properties': {}, 'additionalProperties': {}}, 'description': 'Up to 40 markers: {t, kind} plus optionally code, n, c, span, mode, w, h, top, bottom, tplEpoch. An off-vocabulary kind, an unknown key or a non-integer number refuses the whole batch.'}, 'sessionKey': {'type': 'string', 'description': 'A random id the card minted for THIS mount. Not a user id, not a device id, 6 to 24 lowercase alphanumerics.'}}}
Changed
city_calendar
Sept. 30, 2026, 2:41 a.m.
Changed
city_gis
Sept. 30, 2026, 2:41 a.m.
Changed
city_sweeping
Sept. 30, 2026, 2:41 a.m.
Changed
biz_storefront
Sept. 30, 2026, 2:41 a.m.
Added
biz_order_status
Sept. 30, 2026, 2:41 a.m.
Added
biz_order
Sept. 30, 2026, 2:41 a.m.
Changed
biz_menu
Sept. 30, 2026, 2:41 a.m.
Added
biz_book
Sept. 30, 2026, 2:41 a.m.
Changed
biz_availability
Sept. 30, 2026, 2:41 a.m.
Changed
biz_info
Sept. 30, 2026, 2:41 a.m.
Changed
ui_card_diag
Sept. 30, 2026, 2:41 a.m.
Changed
events_seat_bundle
Sept. 30, 2026, 2:41 a.m.
Changed
events_get
Sept. 30, 2026, 2:41 a.m.
Added
event_accept
Sept. 30, 2026, 2:41 a.m.
Added
event_requests
Sept. 30, 2026, 2:41 a.m.
Added
event_say_hello
Sept. 30, 2026, 2:41 a.m.
Added
event_reply
Sept. 30, 2026, 2:41 a.m.
Added
event_inbox
Sept. 30, 2026, 2:41 a.m.
Added
event_find_matches
Sept. 30, 2026, 2:41 a.m.
Added
event_set_intent
Sept. 30, 2026, 2:41 a.m.
Added
event_redeem_code
Sept. 30, 2026, 2:41 a.m.
Added
biz_set_item_availability
Sept. 30, 2026, 2:41 a.m.
Added
booth_set_away
Sept. 30, 2026, 2:41 a.m.
Added
biz_storefront
Sept. 28, 2026, 2:41 a.m.
Changed
biz_menu
Sept. 28, 2026, 2:41 a.m.
Changed
biz_availability
Sept. 28, 2026, 2:41 a.m.
Changed
biz_info
Sept. 28, 2026, 2:41 a.m.
Changed
ui_card_diag
Sept. 28, 2026, 2:41 a.m.
Added
events_seat_bundle
Sept. 28, 2026, 2:41 a.m.
Changed
city_calendar
Sept. 26, 2026, 2:40 a.m.

SupplyGraph.AI Data

io.github.SupplyGraphAI/daasmart

Provides China-focused location, surrounding-area, company, industry-chain, property, population, retail, and regional business i…

Predicthq

io.github.pipeworx-io/predicthq

Finds and retrieves PredictHQ events, including categories, impact rankings, dates, attendance estimates, and nearby locations.

UK Property & Business Intelligence MCP Server from MCPBundles

com.mcpbundles/uk-property-business

Searches UK companies, officers and filings, charities, geographic names and postcodes, and Great Britain traffic count and flow …

pontofato

com.pontofato/pontofato

Provides Brazilian CEP address lookup, geocoding, radius and proximity searches, address units, and companies associated with loc…

TrustyData

app.trustydata/trustydata

Verifies French addresses, searches companies and localities, computes routes and distance matrices, and provides catchment-area …

Location & Demand Intelligence

com.timzinin.api/location-demand-intelligence

Scores locations, neighborhoods, properties, routes, traffic windows, and operating conditions using official local statistics an…

Public Data Ukraine Mcp

io.github.varvararatta/public_data_ukraine_mcp

Provides Ukrainian geocoding, weather, official exchange rates, and public procurement tender search through public data APIs.

synter-ads

io.github.Synter-Media-AI/synter-ads

Manages cross-platform advertising campaigns, audiences, tracking, creative, landing pages, campaign audits, technology intellige…