Business and service data
An agent has to understand what you sell before it can find you and book you.
Business and service data: Live. Product feed: Planned.
Agents read structured data
SOP turns each business into structured data: the business profile, booking and cancellation rules, and each service's price and duration. The data goes live only after you confirm each item, and you decide which services and time slots are public.
Steps
- Seller → SOP: Profile, services, prices, schedule and cancellation rules
- SOP → SOP: Publishes the listing after the business confirms it
- Agent → SOP: search_businesses
- SOP → Agent: Matching businesses and a few services
- Agent → SOP: get_business
- SOP → Agent: Profile, services with prices and schedules, policies
- Agent → SOP: get_availability
- SOP → Agent: Open slots with prices
Business data
get_business returns the following:
| Field | Description |
|---|---|
business_id, name, categories, city | Business ID, name, categories and city |
profile | Public address, opening hours, booking policy, payment notes, parking, notes and contact |
faq | Frequently asked questions |
quantity | The name and unit for people or places, and the maximum per booking |
online_cancellation | The online cancellation cutoff |
payment | Payment mode: pay at the venue or online, and the payment window |
booking_mode | request_here (book here) or external_link (use the merchant's own booking system) |
Get a business and its services: get_business
curl
curl -sS -X POST https://mcp.srct.tw/mcp \
-H "User-Agent: my-agent/1.0" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"get_business","arguments":{"business_id":"coach-dunken"}}}'
Python
import json
import urllib.error
import urllib.request
BASE = "https://mcp.srct.tw"
def call(method, path, body=None, headers=None):
req = urllib.request.Request(
BASE + path,
data=None if body is None else json.dumps(body).encode(),
method=method,
headers={"User-Agent": "my-agent/1.0", "Content-Type": "application/json", **(headers or {})},
)
try:
with urllib.request.urlopen(req) as res:
return res.status, json.loads(res.read())
except urllib.error.HTTPError as err: # 4xx and 5xx responses still carry a JSON body
return err.code, json.loads(err.read())
def show(status, body):
print("HTTP", status)
print(json.dumps(body, ensure_ascii=False, indent=2))
MCP = {"Accept": "application/json, text/event-stream"} # the server requires both types
show(*call("POST", "/mcp", {"jsonrpc": "2.0", "id": 4, "method": "tools/call", "params": {"name": "get_business", "arguments": {"business_id": "coach-dunken"}}}, MCP))
Node.js
const BASE = "https://mcp.srct.tw";
async function call(method, path, body, headers = {}) {
const res = await fetch(BASE + path, {
method,
headers: { "User-Agent": "my-agent/1.0", "Content-Type": "application/json", ...headers },
body: body === undefined ? undefined : JSON.stringify(body),
});
return { status: res.status, body: await res.json() };
}
function show({ status, body }) {
console.log("HTTP", status);
console.log(JSON.stringify(body, null, 2));
}
const MCP = { Accept: "application/json, text/event-stream" }; // the server requires both types
(async () => {
show(await call("POST", "/mcp", { jsonrpc: "2.0", id: 4, method: "tools/call", params: { name: "get_business", arguments: { business_id: "coach-dunken" } } }, MCP));
})();
Example response
HTTP 200
{
"result": {
"content": [
{
"type": "text",
"text": …
}
],
"structuredContent": {
"ok": true,
"business": {
"business_id": "coach-dunken",
"name": "Dunken教練",
"categories": [
"coaching"
],
"booking_mode": "request_here",
"city": "台北市信義區(Taipei Xinyi)",
"profile": {
"city": "台北市信義區(Taipei Xinyi)",
"address": "…",
"hours": "每天08:00至20:00",
"booking_policy": "取消與改期需在課程開始24小時前(經AI助理線上取消也是開始前24小時截止)。遲到15分鐘將直接結束當次課程,且無法退費。",
"payment": "現金或轉帳。課程一次購買10堂NT$18,000(每堂折合NT$1,800)。",
"notes": "請自行準備合適的訓練服裝,至少提早10分鐘抵達教室。",
"contact": "…"
},
"faq": [],
"quantity": {
"label": "人數",
"unit": "位",
"max_per_booking": 1
},
"online_cancellation": {
"closes_minutes_before_start": 1440,
"text": "Online cancellation closes 24 hours before the start time; after that, contact the business directly."
},
"pending_hold": {
"minutes": 10,
"text": "Bookings that need the business's confirmation are held for 10 minutes. If the business does not confirm by then, the hold is released automatically and the customer can choose another slot."
},
"payment": {
"mode": "venue",
"text": "Pay at the venue."
}
},
"services": [
{
"service_id": "first_assessment",
"name": "初次體能檢查(含InBody一次)",
"category": "一對一",
"summary": "第一次上課:基本動作與體能檢查,並免費做一次InBody身體組成量測(非醫療評估)。",
"price": {
"amount": 0,
"currency": "TWD",
"unit": "每次",
"text": "免費"
},
"duration_min": 60,
"schedule": [
{
"weekday": "sun",
"time": "08:00",
"teacher": "Dunken"
},
{
"weekday": "sun",
"time": "09:00",
"teacher": "Dunken"
},
…
],
"capacity_per_slot": 1,
"teachers": [
"Dunken"
],
"credit_cost": 0
},
…
],
"payment": "Paid services are paid at the venue; services priced at 0 are free. This connector does not take payments."
},
"isError": false
},
"jsonrpc": "2.0",
"id": 4
}Run against the live service (read-only): Shortened for display; … marks omitted parts. result.content[0].text (the same JSON as a string) and the business's address and contact details are omitted.
Service data
Each bookable service has service_id, name, category, summary, a price (amount, currency, unit, text) and a duration duration_min. An agent uses service_id to check availability and create a booking.
Product feed
Retail products need a different kind of data: products, stock, prices and promotions, supplied in batches by the merchant. The status of this part is Planned: there is no product feed import yet, so no format or example is given here.
Compared with a product feed
| Product feed concept | In SOP's service data |
|---|---|
| Basic product data | service_id, name and the business profile |
| Price | price (TWD; booking amounts are in the smallest unit) |
| Availability and inventory | Open slots from get_availability, and capacity per slot |
| Fulfillment | Address, hours, and the booking and cancellation policy |
| Variants | Separate services, each with its own service_id |
| Media, reviews, promotions | Not provided |
Related pages
- Connect to bookings: Search businesses, check availability, create and manage bookings
- Sell products to agents: Our plan for retail products
- Protocols and standards: How MCP, REST, UCP, MPP and x402 map to SOP