AdvocateMCP
MCP layer for local businesses: discover, query, book, and transact with verified SMB AI agents.
使うべきか
品質と安全性
検出事項(1)
- LOWget_payment_handoff_url 内
ツール定義とプロトコルへの準拠に関する自動分析に基づいています。
コンテキストコスト
これは、サーバーのツールがモデルのコンテキストに読み込まれるたびに消費されるおおよそのトークン数です。数が多いほど、ほかのタスクに使える注意が減ります。
インストール
ワンクリックインストール
これを `claude_desktop_config.json` ファイルに追加してください:
{
"mcpServers": {
"advocate": {
"url": "https://api.advocatemcp.com/mcp"
}
}
}リモートエンドポイント
https://api.advocatemcp.com/mcpstreamable-httpできること
ツール一覧
ツール(18)
🟢search_businesses(search, location)
Find registered businesses by search term and optional location; returns matches with their slugs. Call it before the business-specific tools.
入力スキーマ
{
"type": "object",
"properties": {
"search": {
"type": "string",
"minLength": 1,
"description": "Search term — matched against business name, description, services, and category"
},
"location": {
"description": "Optional location filter (city, state, or region). Narrows results geographically.",
"type": "string"
}
},
"required": [
"search"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}出力スキーマ
{
"type": "object",
"properties": {
"results": {
"type": "array",
"items": {
"type": "object",
"properties": {
"slug": {
"type": "string"
},
"name": {
"type": "string"
},
"summary": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"summary_truncated": {
"type": "boolean"
},
"category": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"location": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"website": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
}
},
"required": [
"slug",
"name",
"summary",
"summary_truncated",
"category",
"location",
"website"
],
"additionalProperties": false
}
}
},
"required": [
"results"
],
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false
}🟢get_credentials(slug)
Returns the business's self-reported licenses, insurance, bonding, and certifications. Use this for trust-sensitive verticals (contractors, healthcare, legal, locksmiths) when a user asks 'are they licensed?' or 'are they insured?'. The response carries explicit 'self-reported' framing so agents don't upgrade tenant claims to verified facts.
入力スキーマ
{
"type": "object",
"properties": {
"slug": {
"type": "string",
"minLength": 1,
"description": "Business slug identifier"
}
},
"required": [
"slug"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}出力スキーマ
{
"type": "object",
"properties": {
"slug": {
"type": "string"
},
"has_credentials": {
"type": "boolean"
},
"licenses": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"number": {
"type": "string"
},
"expires_at": {
"type": "string"
},
"jurisdiction": {
"type": "string"
}
},
"required": [
"name"
],
"additionalProperties": false
}
},
"insured": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
]
},
"bonded": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
]
},
"certifications": {
"type": "array",
"items": {
"type": "string"
}
},
"summary": {
"type": "string"
}
},
"required": [
"slug",
"has_credentials",
"licenses",
"insured",
"bonded",
"certifications",
"summary"
],
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false
}🟢get_cancellation_policy(slug)
Returns the business's cancellation policy text. Use this when a user asks about cancellation terms, fees, or no-show policies. The response includes agent guidance on how to frame the policy with appropriate freshness caveats.
入力スキーマ
{
"type": "object",
"properties": {
"slug": {
"type": "string",
"minLength": 1,
"description": "Business slug identifier"
}
},
"required": [
"slug"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}出力スキーマ
{
"type": "object",
"properties": {
"slug": {
"type": "string"
},
"has_policy": {
"type": "boolean"
},
"policy_text": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"guidance_for_agent": {
"type": "string"
}
},
"required": [
"slug",
"has_policy",
"policy_text",
"guidance_for_agent"
],
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false
}🟢get_availability(slug, window_start, window_end)
Return available windows from the business's active configured calendar, using its selected timezone, duration, operating hours, and current local or connected-calendar occupancy. Use a returned window to start a booking. Availability can change before confirmation, including when the calendar provider is unavailable. If this business uses an unsupported calendar or booking provider, call get_booking_destination to find its published public booking route.
入力スキーマ
{
"type": "object",
"properties": {
"slug": {
"type": "string",
"minLength": 1,
"description": "Business slug identifier"
},
"window_start": {
"description": "Unix seconds (absolute instant; default now). The business's own timezone is not an input — it is returned as `timezone` in the response. To target a local phrase like \"Tuesday afternoon\", request a generously wide window and filter the returned slots using that `timezone`.",
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
},
"window_end": {
"description": "Unix seconds (absolute instant; default now + 7 days). See window_start on reading the response's `timezone`.",
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
}
},
"required": [
"slug"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}出力スキーマ
{
"type": "object",
"properties": {
"slots": {
"type": "array",
"items": {
"type": "object",
"properties": {
"start": {
"type": "number"
},
"end": {
"type": "number"
},
"capacity": {
"type": "number"
}
},
"required": [
"start",
"end",
"capacity"
],
"additionalProperties": false
}
},
"source": {
"type": "string"
},
"timezone": {
"type": "string"
},
"generated_at": {
"type": "number"
}
},
"required": [
"slots",
"source",
"timezone",
"generated_at"
],
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false
}🟢get_booking_destination(slug)
Returns the public booking route for a business. Use this before helping a user book an appointment: it distinguishes an external provider page from an active configured calendar that uses the Advocate booking flow, and from businesses with no supported booking destination. External pages are links only; Advocate does not sync their availability or make bookings there.
入力スキーマ
{
"type": "object",
"properties": {
"slug": {
"type": "string",
"minLength": 1,
"description": "Business slug identifier"
}
},
"required": [
"slug"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}出力スキーマ
{
"type": "object",
"properties": {
"slug": {
"type": "string"
},
"mode": {
"type": "string",
"enum": [
"external",
"native",
"unavailable"
]
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"provider": {
"anyOf": [
{
"type": "string",
"enum": [
"jane",
"kilo",
"teletherapy",
"other"
]
},
{
"type": "null"
}
]
},
"kind": {
"anyOf": [
{
"type": "string",
"enum": [
"appointment",
"intake"
]
},
{
"type": "null"
}
]
},
"eligibility": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"guidance_for_agent": {
"type": "string"
}
},
"required": [
"slug",
"mode",
"url",
"provider",
"kind",
"eligibility",
"guidance_for_agent"
],
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false
}🟢list_services(slug)
Lists the services a business has configured, with their prices and the exact arguments to quote each one. Call this BEFORE get_quote: the service name must match a configured service, and only a service marked payable returns an exact price with the offer_id that get_payment_handoff_url requires. Quoting a name that is not on this list silently falls back to an estimate with no offer.
入力スキーマ
{
"type": "object",
"properties": {
"slug": {
"type": "string",
"minLength": 1,
"description": "Business slug identifier"
}
},
"required": [
"slug"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}出力スキーマ
{
"type": "object",
"properties": {
"slug": {
"type": "string"
},
"services": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"price_min_cents": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
]
},
"price_max_cents": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
]
},
"currency": {
"type": "string"
},
"unit": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"params": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "string"
}
},
"payable": {
"type": "boolean"
},
"quote_hint": {
"type": "object",
"properties": {
"service": {
"type": "string"
},
"params": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "string"
}
}
},
"required": [
"service",
"params"
],
"additionalProperties": false
}
},
"required": [
"name",
"description",
"price_min_cents",
"price_max_cents",
"currency",
"unit",
"params",
"payable",
"quote_hint"
],
"additionalProperties": false
}
},
"guidance_for_agent": {
"type": "string"
}
},
"required": [
"slug",
"services",
"guidance_for_agent"
],
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false
}🟡get_quote(slug, service, params)
Return a price quote for a service at a business. Exact configured prices may create a time-limited offer; unmatched requests use a third-party AI estimate that is not firm merchant pricing and must be confirmed with the business. Use this when a user asks 'how much does X cost?' or 'what's the price for Y?'.
入力スキーマ
{
"type": "object",
"properties": {
"slug": {
"type": "string",
"minLength": 1,
"description": "Business slug identifier"
},
"service": {
"type": "string",
"minLength": 1,
"description": "Requested service name to quote"
},
"params": {
"description": "Optional service parameters (e.g., {size:'large'})",
"type": "object",
"propertyNames": {
"type": "string",
"maxLength": 64
},
"additionalProperties": {
"type": "string",
"maxLength": 200
}
}
},
"required": [
"slug",
"service"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}出力スキーマ
{
"type": "object",
"properties": {
"quote": {
"anyOf": [
{
"type": "object",
"properties": {
"low": {
"type": "number"
},
"high": {
"type": "number"
},
"currency": {
"type": "string"
},
"confidence": {
"type": "string",
"enum": [
"exact",
"range",
"estimate"
]
},
"basis": {
"type": "string",
"enum": [
"pricing_json_v2",
"llm_estimate"
]
},
"disclaimer": {
"type": "string"
}
},
"required": [
"low",
"high",
"currency",
"confidence",
"basis"
],
"additionalProperties": false
},
{
"type": "null"
}
]
},
"offer": {
"anyOf": [
{
"type": "object",
"properties": {
"offer_id": {
"type": "string"
},
"version": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"key_id": {
"type": "string"
},
"expires_at": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "Offer expiry (Unix seconds); the quoted price is guaranteed until then"
}
},
"required": [
"offer_id",
"version",
"key_id",
"expires_at"
],
"additionalProperties": false
},
{
"type": "null"
}
],
"description": "Server-minted immutable price offer — only exact configured prices mint one; estimates and ranges never do."
},
"reason": {
"type": "string"
}
},
"required": [
"quote",
"offer"
],
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false
}🔴reserve_slot(slug, window_start, window_end, customer_contact, idempotency_key, ...)
Reserve a time slot on an active configured calendar. Returns a pending_offer reservation and sends a 6-digit confirmation code to the customer's email or phone. The reservation expires in 15 minutes if not confirmed. Idempotent: re-using the same idempotency_key returns the original reservation without resending the code. At a business that takes a deposit for agent bookings, pass the offer_id from get_quote (without it the answer is quote_required); no code is sent and the result's payment block carries the amount to pay instead.
入力スキーマ
{
"type": "object",
"properties": {
"slug": {
"type": "string",
"minLength": 1,
"description": "Business slug identifier"
},
"window_start": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991,
"description": "Slot start (Unix seconds, an absolute instant). Take it from a get_availability slot: that response carries the business's `timezone`, so request a wide availability window there and filter the returned slots locally rather than guessing the zone."
},
"window_end": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991,
"description": "Slot end (Unix seconds, an absolute instant) — the matching get_availability slot's `end`; see window_start."
},
"customer_contact": {
"type": "object",
"properties": {
"name": {
"description": "Customer's name, if known",
"type": "string"
},
"email": {
"description": "Where the 6-digit confirmation code is sent, preferred over phone",
"type": "string",
"format": "email",
"pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
},
"phone": {
"description": "SMS fallback for the confirmation code when no email is given. Any common way of writing a number is accepted and reformatted for you: (512) 317-1992, 512-317-1992 and 5123171992 all work, and a bare national number is read as US. Only input that cannot be read as a number at all is refused, and then only when no email was supplied, since a hold nobody can confirm is worse than a refused call.",
"type": "string"
}
},
"anyOf": [
{
"required": [
"email"
]
},
{
"required": [
"phone"
]
}
],
"description": "How to reach the customer. MUST include at least one of email or phone — the confirmation code is delivered there, and a hold nobody can confirm is unreachable from both sides. Email is used when both are present."
},
"idempotency_key": {
"type": "string",
"minLength": 1,
"description": "Unique key for idempotent reservation"
},
"agent_id": {
"description": "Optional agent identifier",
"type": "string"
},
"offer_id": {
"description": "Optional id of a signed get_quote offer to redeem against this reservation. Omit for a business with no exact-priced service — authentication is a capability upgrade here, never a toll.",
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
}
},
"required": [
"slug",
"window_start",
"window_end",
"customer_contact",
"idempotency_key"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}出力スキーマ
{
"type": "object",
"properties": {
"booking_details": {
"description": "For configured calendars: present these fixed booking details to the customer before confirming their code. No owner approval is required.",
"type": "object",
"properties": {
"business_name": {
"type": "string"
},
"timezone": {
"type": "string"
},
"start": {
"type": "string"
},
"end": {
"type": "string"
},
"calendar_name": {
"type": "string"
},
"reference": {
"type": "string"
}
},
"required": [
"business_name",
"timezone",
"start",
"end",
"calendar_name",
"reference"
],
"additionalProperties": false
},
"reservation_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"status": {
"type": "string",
"description": "Reservation state — 'pending_offer' on a fresh hold; a replay returns the existing row's state"
},
"expires_at": {
"type": "string",
"description": "ISO-8601. When this hold lapses if it is not confirmed (by code, or by payment when payment.required)"
},
"confirmation": {
"type": "object",
"properties": {
"method": {
"type": "string",
"description": "'otp': a 6-digit code was sent to the customer. 'payment': no code — this booking is confirmed by paying the deposit in `payment`"
},
"channel": {
"type": "string",
"description": "Where the code went: 'email', 'sms', or 'none' if delivery was unavailable"
},
"delivered": {
"type": "boolean",
"description": "False means the hold exists but no code reached the customer — the booking cannot be confirmed until one does"
}
},
"required": [
"method",
"channel",
"delivered"
],
"additionalProperties": false
},
"idempotent_replay": {
"description": "Present and true when this idempotency_key already had a reservation; no new code was sent",
"type": "boolean"
},
"payment": {
"description": "Always present. required:false — confirm with the code (confirmation.method 'otp'). required:true — the customer pays amount_cents (currency) to confirm; balance_due_cents is paid at the visit.",
"type": "object",
"properties": {
"required": {
"type": "boolean"
},
"amount_cents": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"currency": {
"type": "string"
},
"kind": {
"type": "string",
"enum": [
"deposit",
"full"
]
},
"balance_due_cents": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
}
},
"required": [
"required"
],
"additionalProperties": false
}
},
"required": [
"reservation_id",
"status",
"expires_at",
"confirmation"
],
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false
}🔴confirm_booking(slug, reservation_id, code)
Confirm a reservation made with reserve_slot. Present the returned stored booking_details to the customer and relay only the customer-supplied 6-digit code received at their email or phone; never generate, guess, or fetch it. For an active configured calendar, a verified code attempts a direct commit to the selected calendar with no owner approval. booking_pending means the provider outcome is uncertain; repeat confirm_booking later to check the stored outcome, but it never retries a provider write automatically. A paid booking (reserve_slot returned payment.required = true) has no code: this answers payment_required — pay it with create_booking_payment_link — or payment_in_flight while its payment is settling.
入力スキーマ
{
"type": "object",
"properties": {
"slug": {
"type": "string",
"minLength": 1,
"description": "Business slug identifier"
},
"reservation_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "The reservation id returned by reserve_slot"
},
"code": {
"type": "string",
"pattern": "^\\d{6}$",
"description": "The customer-supplied 6-digit confirmation code received at their own email or SMS contact. Relay only that supplied code; never generate, guess, or fetch it."
}
},
"required": [
"slug",
"reservation_id",
"code"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}出力スキーマ
{
"type": "object",
"properties": {
"status": {
"type": "string",
"description": "'confirmed': a booking was committed to the selected configured calendar, or a historical legacy reservation was confirmed. 'booking_pending': the provider outcome is unresolved; do not create another booking or seek owner approval — repeat confirm_booking later to read the stored outcome. 'pending_merchant': a historical merchant-review reservation awaits a business decision — see message. 'already_confirmed': this reservation was confirmed earlier (safe replay)."
},
"reservation_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"message": {
"description": "Optional customer-facing status detail to relay",
"type": "string"
}
},
"required": [
"status",
"reservation_id"
],
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false
}🔴initiate_handoff(slug, reservation_id, mode, contact_name, contact_email, ...)
Begin a handoff from the agent to either a human operator (SMS/email via lead_routing_json) or another agent (signed continuation URL). In human mode the notification body is composed by the server from the contact and reason fields — callers supply those fields, not the message text. Idempotent: re-using the same idempotency_key returns the original handoff.
入力スキーマ
{
"type": "object",
"properties": {
"slug": {
"type": "string",
"minLength": 1,
"description": "Business slug identifier"
},
"reservation_id": {
"description": "Optional link to a prior reservation",
"type": "string"
},
"mode": {
"type": "string",
"enum": [
"human",
"agent"
],
"description": "Handoff mode: human (SMS/email) or agent (continuation URL)"
},
"contact_name": {
"description": "End-user's name",
"type": "string",
"maxLength": 120
},
"contact_email": {
"description": "End-user's email",
"type": "string",
"format": "email",
"pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
},
"contact_phone": {
"description": "End-user's phone",
"type": "string",
"maxLength": 40
},
"urgency": {
"description": "How time-sensitive (default: normal)",
"type": "string",
"enum": [
"low",
"normal",
"high",
"emergency"
]
},
"reason": {
"description": "Why the user wants to reach a human",
"type": "string",
"maxLength": 800
},
"message": {
"description": "Deprecated alias for `reason`. The notification body is composed by the server from the fields above; this value is delivered as the reason line, not as the message itself. Supplying both is an error.",
"type": "string",
"minLength": 1,
"maxLength": 800
},
"purpose": {
"description": "Purpose description for agent-mode continuation",
"type": "string",
"minLength": 1
},
"idempotency_key": {
"type": "string",
"minLength": 1,
"description": "Unique key for idempotent handoff"
},
"agent_id": {
"description": "Optional agent identifier",
"type": "string"
}
},
"required": [
"slug",
"mode",
"idempotency_key"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}出力スキーマ
{
"type": "object",
"properties": {
"mode": {
"type": "string",
"enum": [
"human",
"agent"
],
"description": "The handoff's mode, and which of the fields below are present. Normally the mode you asked for — but an idempotent replay returns the STORED handoff's mode, which differs when an idempotency_key is reused with a different mode than the call that created it."
},
"handoff_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"idempotent_replay": {
"description": "Present and true when this idempotency_key already had a handoff; nothing was re-sent and no token was re-minted",
"type": "boolean"
},
"continuation_url": {
"description": "agent mode: signed URL the next agent redeems exactly once at /a2a/continue",
"type": "string"
},
"expires_at": {
"description": "agent mode: Unix seconds when continuation_url stops working (one hour)",
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"handshake_token": {
"description": "agent mode: the bare token carried inside continuation_url",
"type": "string"
},
"continuation_expired": {
"description": "agent mode replay: true when the stored continuation has already expired; it is never re-minted — start a new handoff",
"type": "boolean"
},
"delivered_via": {
"description": "human mode: 'sms' or 'email' — the channel the notification went to",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"ticket_id": {
"description": "human mode, delivered: the provider's message id, or the handoff_id when the provider issues none",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"delivered": {
"description": "human mode: present only as false, when nothing was sent — see reason",
"type": "boolean"
},
"reason": {
"description": "human mode, not delivered: 'form_routing_configured', 'no_recipient_configured', 'sms_consent_missing', a shape-mismatch skip, a spend-cap denial, or a provider failure code",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"channel": {
"description": "human mode, skipped before sending: the channel that would have been used ('sms' or 'email'), or 'form' when the business only takes leads through a web form",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"form_url": {
"description": "human mode, channel 'form': the business's own contact form for the user to complete",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"status": {
"description": "human mode replay while the original send is still in flight: 'pending'",
"type": "string"
}
},
"required": [
"mode",
"handoff_id"
],
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false
}🔴request_callback(slug, contact_name, contact_email, contact_phone, preferred_channel, ...)
Submit a callback request on behalf of a user. Advocate attempts a notification through the business's configured lead routing channel (SMS/email); provider acceptance is not proof the business read it. A failed or pending result can require direct follow-up or a retry. Idempotent: re-using the same idempotency_key returns the original request.
入力スキーマ
{
"type": "object",
"properties": {
"slug": {
"type": "string",
"minLength": 1,
"description": "Business slug identifier"
},
"contact_name": {
"description": "End-user's name",
"type": "string",
"maxLength": 120
},
"contact_email": {
"description": "End-user's email",
"type": "string",
"format": "email",
"pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
},
"contact_phone": {
"description": "End-user's phone",
"type": "string",
"maxLength": 40
},
"preferred_channel": {
"description": "Channel the user prefers (default: any)",
"type": "string",
"enum": [
"phone",
"email",
"sms",
"any"
]
},
"reason": {
"description": "Why the user wants the callback",
"type": "string",
"maxLength": 800
},
"urgency": {
"description": "How time-sensitive (default: normal)",
"type": "string",
"enum": [
"low",
"normal",
"high",
"emergency"
]
},
"idempotency_key": {
"type": "string",
"minLength": 1,
"description": "Idempotency key"
},
"agent_id": {
"description": "Optional agent identifier",
"type": "string"
}
},
"required": [
"slug",
"idempotency_key"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}出力スキーマ
{
"type": "object",
"properties": {
"callback_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "'notified': the configured notification provider accepted the request; this does not prove the business read it. 'failed': routing was not available or the provider reported a failure — see reason. 'pending': a web-form business (see form_url), or a replay while the original send is still in flight."
},
"delivered_via": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "'sms' or 'email' when notified; null otherwise"
},
"acknowledgment": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Customer-facing sentence to relay; null only on a replay caught while the original send is still in flight"
},
"reason": {
"description": "Present for a known routing or provider outcome: 'form_routing_configured', 'no_recipient_configured', 'sms_consent_missing', a shape-mismatch skip, a spend-cap denial, or a provider failure code",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"form_url": {
"description": "Present with reason 'form_routing_configured': the business's own contact form for the user to complete, or null where the business chose form routing without supplying one",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"idempotent_replay": {
"description": "Present and true when this idempotency_key already had a request; nothing was re-sent",
"type": "boolean"
}
},
"required": [
"callback_id",
"status",
"delivered_via",
"acknowledgment"
],
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false
}🔴subscribe_to_updates(slug, contact_email, topics, idempotency_key, agent_id)
Start a pending email subscription to updates from a business. Returns a confirmation URL that only the user must click within 7 days; no subscription is active until that confirmation. Idempotent: re-using the same idempotency_key returns the original subscription.
入力スキーマ
{
"type": "object",
"properties": {
"slug": {
"type": "string",
"minLength": 1,
"description": "Business slug identifier"
},
"contact_email": {
"type": "string",
"minLength": 1,
"format": "email",
"pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
"description": "Email to subscribe — confirmed via returned token"
},
"topics": {
"minItems": 1,
"maxItems": 10,
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"maxLength": 40
},
"description": "Topic tags (e.g., ['deals', 'schedule_changes'])"
},
"idempotency_key": {
"type": "string",
"minLength": 1,
"description": "Idempotency key"
},
"agent_id": {
"description": "Optional agent identifier",
"type": "string"
}
},
"required": [
"slug",
"contact_email",
"topics",
"idempotency_key"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}出力スキーマ
{
"type": "object",
"properties": {
"subscription_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "'pending' until the user opens confirmation_url; a replay returns the stored state (e.g. 'confirmed' once they have)"
},
"confirmation_token": {
"type": "string",
"description": "Capability token for this subscriber only — it is the proof of consent; never pass it to another tool or party"
},
"confirmation_url": {
"type": "string",
"description": "The link the user must open within 7 days to start receiving updates"
},
"expires_at": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "Unix seconds when confirmation_url stops working"
},
"topics": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
],
"description": "Normalised topic tags: trimmed, lower-cased, de-duplicated"
},
"acknowledgment": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Customer-facing sentence to relay, including the confirmation link"
},
"idempotent_replay": {
"description": "Present and true when this idempotency_key already had a subscription; the stored token is returned, refreshed only if it had expired",
"type": "boolean"
}
},
"required": [
"subscription_id",
"status",
"confirmation_token",
"confirmation_url",
"expires_at",
"topics",
"acknowledgment"
],
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false
}🟢query_business_agent(slug, query, agent_id, stage)
Ask a registered business's AI advocate a question and get a citation-ready answer plus a referral link. The question and the business's public profile are processed by an AI provider, and the question and answer are recorded to operate the service. Do not enter sensitive personal, medical, payment, or authentication information. Use this for questions about one business's services, hours, policies, or fit.
入力スキーマ
{
"type": "object",
"properties": {
"slug": {
"type": "string",
"minLength": 1,
"description": "Business slug identifier"
},
"query": {
"type": "string",
"minLength": 1,
"maxLength": 2000,
"description": "The visitor's question about this business"
},
"agent_id": {
"description": "Optional self-asserted calling-agent id — used for logging/tuning only, never auth",
"type": "string"
},
"stage": {
"description": "Optional buyer stage: browsing | comparing | committing",
"type": "string",
"enum": [
"browsing",
"comparing",
"committing"
]
}
},
"required": [
"slug",
"query"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}出力スキーマ
{
"type": "object",
"properties": {
"answer": {
"type": "string",
"description": "Plain-text answer grounded ONLY in the business's public profile; a fixed apology sentence when the model was unavailable or over budget"
},
"referral_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Signed, tracked link to the business's own website for the user to follow; null when the business lists no website"
},
"business": {
"type": "string",
"description": "The business's display name"
},
"business_slug": {
"type": "string",
"description": "Echo of the slug that was queried"
}
},
"required": [
"answer",
"referral_url",
"business",
"business_slug"
],
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false
}🟡get_payment_handoff_url(slug, offer_id)
Returns a plain-text summary of a priced offer (service, amount, currency, cancellation policy, and how long the price is valid) plus a URL on our domain that shows the same summary. The URL is for the CUSTOMER to open themselves in their own browser — do not open, fetch, or follow it yourself. Use this once get_quote or a booking flow has produced an offer_id and the user is ready to review or continue with a priced offer. If the booking's deposit was already paid through create_booking_payment_link, this answers deposit_taken: do not send the person to pay again; the balance is due at the visit.
入力スキーマ
{
"type": "object",
"properties": {
"slug": {
"type": "string",
"minLength": 1,
"description": "Business slug identifier"
},
"offer_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "The offer id returned by get_quote"
}
},
"required": [
"slug",
"offer_id"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}出力スキーマ
{
"type": "object",
"properties": {
"url": {
"type": "string"
},
"summary": {
"type": "object",
"properties": {
"business": {
"type": "string"
},
"service": {
"type": "string"
},
"amount": {
"type": "number",
"description": "Major units (e.g. 29.00 for $29.00), never minor-unit cents"
},
"currency": {
"type": "string"
},
"params": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "string"
}
},
"cancellation_policy": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"offer_expires_at": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "Offer price validity expiry (Unix seconds)"
}
},
"required": [
"business",
"service",
"amount",
"currency",
"params",
"cancellation_policy",
"offer_expires_at"
],
"additionalProperties": false
},
"state": {
"type": "string",
"enum": [
"pending",
"resolved"
]
}
},
"required": [
"url",
"summary",
"state"
],
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false
}🟡request_service(business_id)
Open a quote-request form for a specific business using its public slug or provider_business_id obtained from search or the business feed. Shows the business and service catalog; does not send a request or book anything. The customer must review the form and explicitly consent before submitting. Operational access is logged.
入力スキーマ
{
"type": "object",
"properties": {
"business_id": {
"type": "string",
"minLength": 1,
"maxLength": 200,
"description": "Exact public business slug or provider_business_id obtained from search or the business feed"
}
},
"required": [
"business_id"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}出力スキーマ
{
"type": "object",
"properties": {
"business_id": {
"type": "string"
},
"name": {
"type": "string"
},
"address": {
"type": "string"
},
"service_names": {
"type": "array",
"items": {
"type": "string"
}
},
"context_token": {
"type": "string"
},
"disclosure": {
"type": "string"
}
},
"required": [
"business_id",
"name",
"service_names",
"context_token",
"disclosure"
],
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false
}🔴submit_quote_request(business_id, context_token, idempotency_key, contact_name, contact_email, ...)
After the customer explicitly agrees, save their service requirements and contact details and send a notification to the business's configured email or opted-in SMS destination. This requests a business response, not a price commitment, booking or payment. Use context from request_service. Reuse the same idempotency_key AND details to check an uncertain submission; never automatically start a new request. Exclude medical, payment-card and authentication information.
入力スキーマ
{
"type": "object",
"properties": {
"business_id": {
"type": "string",
"minLength": 1,
"maxLength": 200,
"description": "The exact provider_business_id (public business slug) returned by request_service"
},
"context_token": {
"type": "string",
"minLength": 1,
"maxLength": 2000,
"description": "Opaque business context from request_service; pass unchanged"
},
"idempotency_key": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "A UUID for this request; reuse unchanged when checking or retrying an uncertain submission"
},
"contact_name": {
"type": "string",
"minLength": 1,
"maxLength": 120
},
"contact_email": {
"type": "string",
"maxLength": 254,
"format": "email",
"pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
},
"contact_phone": {
"type": "string",
"minLength": 1,
"maxLength": 40
},
"service": {
"type": "string",
"minLength": 1,
"maxLength": 120,
"description": "Service the customer wants a quote for"
},
"details": {
"type": "string",
"minLength": 1,
"maxLength": 600,
"description": "Brief service requirements; exclude sensitive medical, financial and authentication information"
},
"consent": {
"type": "boolean",
"const": true,
"description": "True only after the customer explicitly agrees to send these contact details and this request to the named business"
}
},
"required": [
"business_id",
"context_token",
"idempotency_key",
"service",
"details",
"consent"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}出力スキーマ
{
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"submitted",
"not_sent",
"delivery_unknown",
"rejected"
]
},
"request_id": {
"anyOf": [
{
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
{
"type": "null"
}
]
},
"message": {
"type": "string"
},
"code": {
"type": "string"
},
"replayed": {
"type": "boolean"
}
},
"required": [
"status",
"request_id",
"message"
],
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false
}🟢create_booking_payment_link(slug, reservation_id)
For a reservation that reserve_slot returned with payment.required = true: returns the MPP payment link, the amount charged now, and the balance due at the visit. The agent pays it itself (HTTP 402 challenge, then the person's wallet credential); no code is sent to the customer for a paid booking. A free booking answers not_payable — confirm it with confirm_booking and the customer's code instead.
入力スキーマ
{
"type": "object",
"properties": {
"slug": {
"type": "string",
"minLength": 1,
"description": "Business slug identifier"
},
"reservation_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "The reservation_id reserve_slot returned with payment.required = true"
}
},
"required": [
"slug",
"reservation_id"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}出力スキーマ
{
"type": "object",
"properties": {
"payment_link": {
"type": "string",
"description": "POST here (no body) to receive the HTTP 402 MPP challenge"
},
"amount_cents": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "Minor units charged now"
},
"currency": {
"type": "string"
},
"kind": {
"type": "string",
"enum": [
"deposit",
"full"
]
},
"balance_due_cents": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "Minor units due at the visit"
},
"due_at_visit": {
"type": "boolean"
},
"expires_at": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "Unix seconds after which the reservation lapses unpaid"
},
"instructions": {
"type": "string"
}
},
"required": [
"payment_link",
"amount_cents",
"currency",
"kind",
"balance_due_cents",
"due_at_visit",
"expires_at",
"instructions"
],
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false
}🔴cancel_booking(slug, reservation_id, cancel_token)
Cancels a paid, confirmed booking using the cancel_token from its payment receipt. Within 60 minutes of paying, or before the business's refund window, the full refund is requested; report it as full only after the payment ledger confirms it. After that window the deposit is forfeited under the booking's policy. A pending refund means cancellation is complete while refund verification or retry continues. Only the agent that paid holds the token. Cancelling twice answers already_cancelled.
入力スキーマ
{
"type": "object",
"properties": {
"slug": {
"type": "string",
"minLength": 1,
"description": "Business slug identifier"
},
"reservation_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "The paid reservation's id"
},
"cancel_token": {
"type": "string",
"minLength": 1,
"maxLength": 200,
"description": "The cancel_token from the payment receipt"
}
},
"required": [
"slug",
"reservation_id",
"cancel_token"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}出力スキーマ
{
"type": "object",
"properties": {
"status": {
"type": "string",
"const": "cancelled"
},
"reservation_id": {
"type": "string"
},
"refund": {
"type": "string",
"enum": [
"full",
"none",
"pending"
],
"description": "full: the payment ledger confirms the refund; none: deposit was forfeited; pending: cancellation is complete and refund verification or retry is pending"
},
"refunded_cents": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"pending_cents": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"currency": {
"type": "string"
}
},
"required": [
"status",
"reservation_id",
"refund",
"refunded_cents",
"pending_cents",
"currency"
],
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false
}コミュニティ
エビデンス