Kirah Local Services
Server Details
Discover local services and availability, then create, track, reschedule, or cancel bookings.
- Status
- Healthy
- Last Tested
- Transport
- Streamable HTTP
- URL
TDQS
Scored across 10 tools
Each booking lifecycle tool is clearly distinct, and the search/availability tools are generally separated by scope. The closest pair is find_available_services and get_availability, but their descriptions sufficiently distinguish cross-business availability checks from per-service calendar lookups.
All tool names follow a consistent snake_case verb_noun pattern, such as create_booking, get_availability, list_services, and reschedule_booking. The verbs are predictable and communicate the action clearly.
Ten tools is a well-scoped size for a local services booking server. Each tool addresses a distinct part of the workflow without unnecessary redundancy or bloat.
The tool set covers the core booking journey: discovery, availability, booking creation, status checks, rescheduling, and cancellation. A minor gap is the lack of a list-bookings endpoint, though payment is explicitly handled outside MCP, so core functionality remains intact.
Available Tools
10 toolscancel_bookingCancel bookingADestructiveInspect
Cancels one grant-authorized booking after explicit user confirmation. Reusing idempotency_key makes retries safe. Kirah refuses cancellations that could refund a charged deposit or restore a paid plan session; an allowed cancellation has no undo.
| Name | Required | Description | Default |
|---|---|---|---|
| grant | Yes | The capability token from this booking's create_booking response (confirmation.grant). Required: without it there is no way to establish that you are the agent that made this booking. It must carry the `booking:cancel` scope. Tampered, wrong-booking, wrong-tenant, revoked and insufficiently-scoped grants all answer invalid_grant, indistinguishably; an authentic grant past the appointment start answers expired_grant. | |
| tenant | Yes | The tenant to operate on: the provider.tenant_slug value from the tenant's /.well-known/kirah.json manifest (the tenant's full domain, e.g. <slug>.kirah.ai). | |
| booking_ref | Yes | The reference create_booking returned for the booking you want to CANCEL. It must be the SAME booking the supplied grant was issued for; a mismatch answers invalid_grant, indistinguishably from a forged grant. | |
| agent_metadata | No | ||
| idempotency_key | Yes | REQUIRED — unlike create_booking, this action cannot derive one, because "cancel booking X" is byte-identical whether it is a transport retry or a deliberate second call. Omitting it answers missing_idempotency_key. Reuse the SAME key when retrying the SAME cancellation: the replay returns the original result with idempotent_replay:true, cancels nothing and sends no second notice. The same key against a different booking_ref answers idempotency_conflict. |
Output Schema
| Name | Required | Description |
|---|---|---|
| demo | No | |
| grant | No | |
| detail | No | |
| reason | No | |
| end_iso | No | |
| missing | No | |
| outcome | Yes | |
| notified | No | |
| start_iso | No | |
| policy_fee | No | |
| request_id | No | |
| booking_ref | No | |
| booking_url | No | |
| demo_notice | No | |
| intake_form | No | |
| payment_url | No | |
| confirmation | No | |
| service_name | No | |
| deposit_cents | No | |
| provider_name | No | |
| status_reason | No | |
| appointment_id | No | |
| policy_message | No | |
| retry_after_sec | No | |
| cancel_fee_cents | No | |
| already_cancelled | No | |
| idempotent_replay | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the destructiveHint annotation, the description discloses that an allowed cancellation has no undo, that unsafe refund/restore cancellations are refused, and that reusing the idempotency_key makes retries safe. This gives the agent critical behavioral expectations not available from annotations or the schema alone.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three tight sentences with no filler. It front-loads the primary action and confirmation requirement, then covers retry safety and refusal constraints. Every sentence contributes either to correct invocation or to setting the correct risk expectation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's destructive nature, the description covers the essential operational guardrails: user confirmation, grant authorization, idempotent retries, refusal conditions, and irreversibility. An output schema exists, so return-value documentation is not the description's responsibility. The description is complete enough for an agent to use the tool safely and correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 80%, with grant, booking_ref, tenant, and idempotency_key already well documented in the schema. The description adds contextual emphasis on the grant requirement and idempotency safety, but it does not materially expand parameter meaning beyond what the schema already provides. A baseline 3 is appropriate given the high schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Cancels one grant-authorized booking'. The phrase 'after explicit user confirmation' and the cancellation-specific constraints clearly distinguish this tool from siblings like reschedule_booking or get_booking_status. The purpose is unambiguous and immediately usable by an agent.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear when-to-use context: cancellation only after explicit user confirmation, and only for grant-authorized bookings. It also states a when-not condition by describing cancellations Kirah refuses (those that refund a charged deposit or restore a paid plan session). It does not explicitly name alternatives such as reschedule_booking, but the cancellation scope is clear enough for correct tool selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_bookingCreate bookingADestructiveInspect
Creates one guest booking for an exact service, provider and ISO-8601 start time after explicit user confirmation. Reusing idempotency_key makes retries safe. Kirah accepts no payment credentials through MCP; a deposit-required service may return a Kirah-hosted human payment continuation, but this call transfers no funds.
| Name | Required | Description | Default |
|---|---|---|---|
| client | Yes | ||
| tenant | Yes | The tenant to operate on: the provider.tenant_slug value from the tenant's /.well-known/kirah.json manifest (the tenant's full domain, e.g. <slug>.kirah.ai). | |
| start_iso | Yes | ||
| service_id | Yes | ||
| provider_id | No | ||
| agent_metadata | No | ||
| idempotency_key | No | ||
| intake_responses | No | Answers to the service's intake form (2.8), keyed by intake field id as advertised in list_services' service.intake_form.fields[].id. FLAT only: values must be a string, a boolean, or a finite number — arrays, nested objects and nulls are rejected. Unknown keys are ignored by the booking engine. Answers are validated against the LIVE form; a required plain boolean accepts an explicit true OR false, a consent boolean accepts only true, and a select must exactly match one advertised option. Omit this field entirely when the service has no intake form. |
Output Schema
| Name | Required | Description |
|---|---|---|
| demo | No | |
| grant | No | |
| detail | No | |
| reason | No | |
| end_iso | No | |
| missing | No | |
| outcome | Yes | |
| notified | No | |
| start_iso | No | |
| policy_fee | No | |
| request_id | No | |
| booking_ref | No | |
| booking_url | No | |
| demo_notice | No | |
| intake_form | No | |
| payment_url | No | |
| confirmation | No | |
| service_name | No | |
| deposit_cents | No | |
| provider_name | No | |
| status_reason | No | |
| appointment_id | No | |
| policy_message | No | |
| retry_after_sec | No | |
| cancel_fee_cents | No | |
| already_cancelled | No | |
| idempotent_replay | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, the description discloses important behaviors: retry safety via idempotency_key, that no funds are transferred, that payment credentials are not accepted, and that a deposit-required service may return a Kirah-hosted human payment continuation. These are meaningful, non-obvious side effects and boundaries not encoded in the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences with no filler. The primary action and user-confirmation requirement come first, followed by idempotency guidance and the payment caveat, which is an effective front-loaded structure.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity and the presence of an output schema, the description covers the essential non-obvious context: exact-match booking, confirmation requirement, retry semantics, and payment behavior. It does not explain how to obtain service_id or provider_id from sibling tools, but the input schema and output schema cover most remaining structural detail.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is low at 25%, and the description compensates only partially. It adds meaning to start_iso by requiring ISO-8601, and to idempotency_key by explaining safe retries, but it leaves tenant, client, agent_metadata, and intake_responses semantics to the schema and parameter names.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Creates one guest booking for an exact service, provider and ISO-8601 start time.' The explicit constraints and the user-confirmation gate make its purpose unmistakable and clearly distinct from siblings like cancel_booking and reschedule_booking.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear invocation conditions: call only after explicit user confirmation, reuse idempotency_key for safe retries, and do not expect to pass payment credentials through MCP. It provides strong usage context but does not explicitly name alternatives or say when not to use this tool, so it stops short of full routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_available_servicesFind available services (earliest openings)ARead-onlyInspect
Checks up to five top matching eligible Kirah businesses for earliest current availability within an exact ISO-8601 window of up to 14 days. Returns checked status and a partial-coverage flag.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | The consumer's service need in plain words — identical semantics to search_businesses.query. | |
| location | No | Optional place text ('City, ST', ZIP, bare city/state) OR explicit coordinates 'lat,lng' — identical semantics to search_businesses.location. | |
| tenant_mode | No | The authoritative demo eligibility filter, with the same semantics as search_businesses. include_demos is the default and returns real and demo candidates; real_only excludes demos; demos_only returns only clearly labeled demonstration candidates. | include_demos |
| include_demo | No | Back-compat alias: true is equivalent to tenant_mode 'include_demos' and false to 'real_only'. When omitted, tenant_mode defaults to include_demos. Every demo candidate carries demo:true and a demo_notice. Supplying both include_demo and tenant_mode with disagreeing demo-inclusion is invalid_tenant_mode. | |
| radius_miles | No | Radius in miles (default 25) — operative when the location resolves to coordinates (2.6 semantics). | |
| earliest_after | No | Exact ISO 8601 instant the window opens (default: now). Natural-language times are rejected (invalid_earliest_after). | |
| candidate_limit | No | How many top-matching businesses get LIVE availability checks (invalid_candidate_limit outside 1-5). This bounds the whole fan-out: businesses beyond it are never touched, and partial:true says so. | |
| earliest_before | No | Exact ISO 8601 instant the window closes (default: earliest_after + 14 days). Must be after earliest_after and at most 14 days after it (invalid_earliest_before). | |
| max_price_cents | No | Only candidate services with a parseable price at or under this amount are considered. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only, open-world, and non-destructive behavior. The description adds meaningful behavioral context: bounded fan-out to up to five businesses, an exact ISO-8601 window capped at 14 days, and a partial-coverage signal instead of pretending results are exhaustive. It does not discuss rate limits or auth, but those are less critical for a read-only opener-style tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is one tight, front-loaded sentence: it states what is checked, the candidate bound, the window rule, and the key return signal. There is no filler, no restatement of the tool name, and no wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the comprehensive input schema, the presence of an output schema, and annotations that establish safety and open-world behavior, the description supplies the high-level invocation model an agent needs: what is searched, how many candidates are touched, the window format, and partial-coverage semantics. It is complete for a read-only tool of this complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
All nine parameters have full schema descriptions, defaults, constraints, and error semantics, so the baseline is 3. The description does not add parameter-level meaning beyond what the schema already documents; it mostly summarizes candidate_limit and window behavior already present in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a concrete operation ('Checks up to five top matching eligible Kirah businesses for earliest current availability') and specifies scope, window constraints, and return behavior ('checked status and a partial-coverage flag'). This clearly distinguishes it from pure search or listing siblings like search_businesses, search_services, and list_services.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The use case is reasonably implied—find earliest openings across several matching businesses—but the description never explicitly says when to prefer this over get_availability or search_services, nor gives a when-not-to-use caveat. An agent can infer the intended usage, but the guidance is not explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_availabilityGet availabilityARead-onlyInspect
Returns current open times for one exact service and optional provider over a YYYY-MM-DD range of up to 31 days, with at most 20 rows. Approval-mode times are preferences rather than holds.
| Name | Required | Description | Default |
|---|---|---|---|
| tenant | Yes | The tenant to operate on: the provider.tenant_slug value from the tenant's /.well-known/kirah.json manifest (the tenant's full domain, e.g. <slug>.kirah.ai). | |
| date_range | Yes | ||
| service_id | Yes | ||
| provider_id | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish readOnly/non-destructive, but the description adds non-obvious behavior: results are limited to 31 days and 20 rows, and approval-mode times are preferences rather than holds. This materially changes how an agent should interpret results.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence where each clause delivers a distinct constraint or caveat. There is no filler, repetition, or redundant restating of the tool name.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With output schema and annotations present, the description covers the operational constraints that affect invocation and interpretation: range cap, row cap, and approval-mode semantics. Nothing essential is missing for correct tool use.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is low (25%), but the description compensates: it identifies service_id as an exact service, provider_id as optional, and constrains date_range to YYYY-MM-DD up to 31 days. Tenant semantics are already well-documented in the schema, so the gap is acceptable.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Returns'), a concrete resource ('current open times'), and the selection scope ('one exact service and optional provider') with range limits. This makes it distinct from sibling service-discovery tools like find_available_services, which work across services.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It clearly implies the call context: the caller must already know the exact service (service_id is required) and a date range, with provider optional. It doesn't explicitly name alternatives or exclusions, so it stops short of a full when-to-use/when-not-to-use guide.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_booking_statusGet booking statusARead-onlyInspect
Returns the current status, time, service and provider for one grant-authorized booking reference. Client contact details and intake responses are excluded.
| Name | Required | Description | Default |
|---|---|---|---|
| grant | No | The booking-bound capability token returned by create_booking. It must match this tenant and booking_ref and remain unexpired and unrevoked. | |
| tenant | Yes | The tenant to operate on: the provider.tenant_slug value from the tenant's /.well-known/kirah.json manifest (the tenant's full domain, e.g. <slug>.kirah.ai). | |
| booking_ref | Yes | The reference create_booking returned (its idempotency key). Tampered, unrelated, cross-tenant or never-committed references answer one indistinguishable booking_not_found. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds meaningful behavior beyond annotations by explicitly stating that client contact details and intake responses are excluded from the result, and by emphasizing the grant-authorized scope. This gives the agent important information about data privacy boundaries without contradicting any annotation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler. The first sentence front-loads the core purpose and scope, and the second adds a meaningful exclusion. Every word earns its place, and the description is easy to scan quickly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the presence of an output schema, all parameters documented, and safety annotations in place, the description is largely complete for a simple status lookup. It could mention when to use it relative to siblings or note error semantics, but those are not critical for a read-only retrieval tool with rich structured metadata around it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all three parameters thoroughly. The description does not add new parameter-level semantics beyond restating that the booking reference must be grant-authorized, which the booking_ref and grant parameter descriptions already cover. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Returns') plus a concrete resource: 'current status, time, service and provider for one grant-authorized booking reference.' It also clarifies what is excluded ('Client contact details and intake responses are excluded'), which sharply differentiates it from sibling mutation tools like cancel_booking or reschedule_booking. An agent can tell this is a read-only status lookup without ambiguity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no explicit guidance on when to use this tool versus alternatives. It implies a context through 'grant-authorized booking reference,' but it does not state when this should be preferred over get_reschedule_options, find_available_services, or any other sibling. No when-not or alternative routing is mentioned.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_reschedule_optionsGet reschedule optionsARead-onlyInspect
Returns up to five real alternate times and the current fee or approval consequences for one grant-authorized booking. It does not hold, move or cancel the appointment.
| Name | Required | Description | Default |
|---|---|---|---|
| grant | Yes | The capability token from this booking's create_booking response (confirmation.grant). Required: without it there is no way to establish that you are the agent that made this booking. Tampered, wrong-booking, wrong-tenant and revoked grants all answer invalid_grant, indistinguishably; an authentic grant past the appointment start answers expired_grant. These are the GRANT codes, not the payment page's invalid_token/expired_token — through contract 2.11 this action answered the latter, whose prose wrongly told callers their payment link was broken. | |
| limit | No | How many options to return. Default 2, hard maximum 5; a larger value is CLAMPED to 5 rather than rejected. The ceiling is deliberate: the primary consumer is a voice agent reading options aloud, and five spoken times is more than a caller can hold in their head. | |
| latest | No | Optional exact ISO 8601 instant — the latest replacement time to consider. Default: now + 14 days. Must be after `earliest` and at most 31 days after it; anything else answers invalid_latest. Supply it explicitly whenever `earliest` is more than 14 days out. | |
| tenant | Yes | The tenant to operate on: the provider.tenant_slug value from the tenant's /.well-known/kirah.json manifest (the tenant's full domain, e.g. <slug>.kirah.ai). | |
| earliest | No | Optional exact ISO 8601 instant — the earliest replacement time to consider. Default: now + 2 hours (a slot the customer cannot physically reach is not an option). Natural-language times are not accepted. | |
| booking_ref | Yes | The reference create_booking returned (its idempotency key). It must be the SAME booking the supplied grant was issued for; a mismatch answers invalid_grant, indistinguishably from a forged grant. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds genuine value beyond them: options are not held or reserved, and the response surfaces current fee/approval consequences — a behavioral trait an agent needs before promising a customer a fee-free reschedule. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, both load-bearing: the first states the deliverable (times plus fee/approval consequences), the second the critical exclusions. Information is front-loaded with zero filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With 100% schema coverage, rich annotations, an output schema covering return shape, and param-level descriptions of error codes and defaults, the short description completes the picture. Nothing an agent needs to invoke this tool correctly is absent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and each parameter's schema description is exceptionally detailed (grant error-code semantics, limit clamping behavior, earliest/latest defaults and constraints). Per baseline, the description need not compensate; it adds no parameter detail but nothing is missing either.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource — returns alternate times and fee/approval consequences for one grant-authorized booking. The second sentence explicitly excludes hold/move/cancel behaviors, cleanly distinguishing it from reschedule_booking and cancel_booking in the sibling list.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'does not hold, move or cancel the appointment' clause is an explicit when-not statement telling an agent this is a preview, not a mutation. It stops short of naming the alternatives directly (reschedule_booking, cancel_booking), though the sibling names plus the grant-authorized scoping make the intended position in the workflow clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_servicesList servicesARead-onlyInspect
Returns one published Kirah business catalog with current services, providers, timezone, prices, durations, deposit requirements, intake-question definitions and derived booking capabilities.
| Name | Required | Description | Default |
|---|---|---|---|
| tenant | Yes | The tenant to operate on: the provider.tenant_slug value from the tenant's /.well-known/kirah.json manifest (the tenant's full domain, e.g. <slug>.kirah.ai). |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, covering the safety profile. The description adds meaningful behavioral context beyond the annotations by specifying that it returns 'one published' catalog and enumerating the exact data categories included, including 'derived booking capabilities.'
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single front-loaded sentence that begins with the action and resource, then efficiently lists all catalog contents in a compact enumeration. Every element adds information, with no filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only listing tool with one well-documented parameter and an output schema, the description is complete: it states the scope ('one published'), the resource type, and the full set of returned data categories. No critical selection or behavioral information is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single parameter 'tenant' already has a thorough schema description covering its source and format, and schema description coverage is 100%. The tool description does not need to add parameter details, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Returns') and names the resource ('Kirah business catalog') with a detailed list of contents: services, providers, timezone, prices, durations, deposits, intake questions, and derived booking capabilities. This clearly differentiates it from siblings like find_available_services or search_services, which focus on availability or search rather than the full published catalog.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly implies this is the tool for retrieving the full published catalog, but it does not explicitly state when to choose it over alternatives like find_available_services or search_services. There are no exclusions or direct comparisons to sibling tools, so the usage context is inferred rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
reschedule_bookingReschedule bookingADestructiveInspect
Atomically moves one grant-authorized booking to a real open time after explicit user confirmation. Reusing idempotency_key makes retries safe. Failure leaves the original booking unchanged; success returns a rotated grant.
| Name | Required | Description | Default |
|---|---|---|---|
| grant | Yes | The capability token from this booking's create_booking response (confirmation.grant). Required: without it there is no way to establish that you are the agent that made this booking. It must carry the `booking:reschedule` scope. Tampered, wrong-booking, wrong-tenant, revoked and insufficiently-scoped grants all answer invalid_grant, indistinguishably; an authentic grant past the appointment start answers expired_grant. These are the GRANT codes, not the payment page's invalid_token/expired_token — through contract 2.11 this action answered the latter, whose prose wrongly told callers their payment link was broken. | |
| tenant | Yes | The tenant to operate on: the provider.tenant_slug value from the tenant's /.well-known/kirah.json manifest (the tenant's full domain, e.g. <slug>.kirah.ai). | |
| start_iso | Yes | The exact ISO 8601 instant to move the appointment to. Natural-language times are not accepted. You may supply it DIRECTLY — calling get_reschedule_options first is optional, not required — because the instant is validated against real availability by the same slot engine create_booking uses. A time that is not genuinely open answers slot_taken with the original booking untouched; a time further ahead than this business books answers beyond_booking_horizon. | |
| booking_ref | Yes | The reference create_booking returned for the booking you want to MOVE. It must be the SAME booking the supplied grant was issued for; a mismatch answers invalid_grant, indistinguishably from a forged grant. A successful move does not change it. | |
| provider_id | No | OPTIONAL. Move the booking to a different provider. Omit it and the booking keeps the provider it is already on — the customer booked a person, not a room. An explicit provider is honored only when that provider exists in this tenant's catalog (else unknown_provider) AND performs the booked service (else provider_service_mismatch). The service and its duration never change. | |
| agent_metadata | No | ||
| idempotency_key | Yes | REQUIRED — unlike create_booking, this action cannot derive one, because "move booking X to time T" is byte-identical whether it is a retry or a deliberate second move. Omitting it answers missing_idempotency_key. Reuse the SAME key when retrying the SAME move: the replay returns the original result with idempotent_replay:true and moves nothing. The same key with a different start_iso or provider_id answers idempotency_conflict. |
Output Schema
| Name | Required | Description |
|---|---|---|
| demo | No | |
| grant | No | |
| detail | No | |
| reason | No | |
| end_iso | No | |
| missing | No | |
| outcome | Yes | |
| notified | No | |
| start_iso | No | |
| policy_fee | No | |
| request_id | No | |
| booking_ref | No | |
| booking_url | No | |
| demo_notice | No | |
| intake_form | No | |
| payment_url | No | |
| confirmation | No | |
| service_name | No | |
| deposit_cents | No | |
| provider_name | No | |
| status_reason | No | |
| appointment_id | No | |
| policy_message | No | |
| retry_after_sec | No | |
| cancel_fee_cents | No | |
| already_cancelled | No | |
| idempotent_replay | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds significant behavioral detail beyond the annotations: atomicity, idempotent retries via idempotency_key, failure leaving the original booking unchanged, and success returning a rotated grant. These are not available from annotations alone and materially improve an agent's understanding of side effects and retry behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The main description is three tight sentences that front-load the core action, then cover atomicity, idempotency, failure behavior, and success behavior. Every sentence earns its place, and the extensive parameter details live where they belong in the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is complex with 7 parameters and nested objects, but the schema descriptions are comprehensive, an output schema exists, and annotations convey read-only vs destructive intent. The description covers the behavioral guarantees an agent needs, including the crucial requirement of explicit user confirmation, so nothing critical is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is high at 86%, so the baseline is 3. The top-level description itself adds little parameter-specific meaning beyond idempotency_key reuse, while the input schema already provides rich semantics for grant, start_iso, booking_ref, provider_id, and idempotency_key, including error codes and constraints.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: "Atomically moves one grant-authorized booking to a real open time." It distinguishes this from siblings like create_booking, cancel_booking, and get_reschedule_options by emphasizing that this acts on an existing booking with a grant and after explicit user confirmation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly implies the booking already exists and requires a grant, which establishes when this tool is appropriate. The start_iso parameter adds explicit guidance that get_reschedule_options is optional, not required. It does not explicitly enumerate when not to use it versus cancel_booking or create_booking, but the context is clear enough.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_businessesSearch Kirah businessesARead-onlyInspect
Searches Kirah's eligible public business directory by service need or exact Kirah Agent Address, with optional coarse location, price and demo-mode filters. Demo results are explicitly labeled.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | No | The consumer's need in plain words (e.g. 'lower back tightness', 'prenatal massage'). Matched deterministically against real service catalogs, expanded by the discovery ontology. | |
| cursor | No | Opaque next_cursor value from a previous search_businesses response with the SAME query/filters: resumes after that tenant in the stable ordering. A cursor that does not decode, or that names a tenant not present in the current ordering, is invalid_cursor. | |
| location | No | Optional place text ('City, ST', ZIP, bare city/state) OR explicit coordinates 'lat,lng'. With resolvable coordinates, radius_miles applies as real distance; otherwise matching is city/ZIP/metro-market text equality. | |
| tenant_mode | No | The authoritative eligibility filter for demo tenants. include_demos (default) returns real and demo businesses together; every demo is flagged demo:true and carries a clear notice. real_only excludes every demo business; demos_only returns ONLY demo businesses. A discovery-disabled, inactive, or otherwise ineligible tenant never appears in any mode — not even when its catalog uniquely matches the query. | include_demos |
| include_demo | No | Back-compat alias: true is equivalent to tenant_mode 'include_demos' and false to 'real_only'. When omitted, tenant_mode defaults to include_demos. Every demo result carries demo:true and a demo_notice. Supplying both include_demo and tenant_mode with disagreeing demo-inclusion is invalid_tenant_mode. | |
| radius_miles | No | Radius in miles (default 25) — OPERATIVE when the location resolves to coordinates (2.6); otherwise answered with a truthful distance_note instead of a fabricated distance. | |
| agent_address | No | Exact public locator `<handle>@kirah.ai`; case-insensitive ASCII only. A locator, never authentication or owner authority. Reserved, malformed, unlisted, disabled, non-bookable, and tenant_mode-ineligible addresses do not resolve. Exact mode never fuzzy-matches a near miss. | |
| max_price_cents | No | Only services with a parseable price at or under this amount are returned; unpriced services are excluded when this is set. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish readOnlyHint=true, openWorldHint=true, and destructiveHint=false, so the safety profile is covered. The description adds useful context about eligibility and explicitly labeled demo results, but it does not disclose behaviors like exact-no-fuzzy matching or the nuanced tenant-mode exclusions; those are left to the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences lead with the core purpose and then highlight the most important behavioral caveat, demo labeling. Every phrase earns its place, with no redundant restatement of schema details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the rich input schema, output schema, and annotations, the description is largely complete for selection purposes. It could be improved by naming the intended alternative to search_services and by surfacing a couple of key edge behaviors, but an agent can reasonably call the tool correctly from this definition.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 89%, so the schema carries most parameter meaning. The description adds a useful high-level grouping—service need, exact address, location, price, and demo-mode filters—but does not materially extend what the parameter descriptions already provide.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: searching Kirah's eligible public business directory, and names the two principal lookup modes (service need or exact agent address). It does not explicitly distinguish itself from siblings like search_services, so it falls short of full sibling differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use the tool: when looking up businesses by a service need or by an exact Kirah address, with optional location/price/demo filters. It gives no explicit guidance about when a sibling such as search_services or list_services would be more appropriate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_servicesSearch servicesARead-onlyInspect
Ranks up to five services in one published Kirah business catalog against a short free-text query. Returns catalog-grounded candidate identifiers, names, scores and match evidence.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | ||
| tenant | Yes | The tenant to operate on: the provider.tenant_slug value from the tenant's /.well-known/kirah.json manifest (the tenant's full domain, e.g. <slug>.kirah.ai). |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and destructiveHint false. The description adds meaningful behavioral context: the ranking cap of five results, catalog grounding, and the exact return payload (identifiers, names, scores, match evidence). This goes beyond the annotations and sets clear expectations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two tight sentences with no filler. It front-loads the core purpose and limitation, then lists the return contents. Every sentence adds value without repeating schema details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only search tool with an output schema and annotations covering safety, the description covers scope, ranking limit, and return payload. The only notable gap is the absence of explicit guidance on when to prefer this tool over sibling tools.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tenant parameter is already well documented in the schema, and the description adds only modest meaning for the query parameter by calling it 'short free-text query' and tying it to ranking. With 50% schema description coverage, the description partially compensates but does not fully explain parameter semantics on its own.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description identifies a specific action — ranking services against a free-text query — and names the resource (services in one published Kirah business catalog) and output components. It is clear and specific, though it does not explicitly distinguish itself from sibling search/list tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The tool's use case is implied through the phrasing 'ranks up to five services against a short free-text query,' which suggests free-text discovery rather than listing or availability checks. However, there is no explicit when-to-use/when-not-to-use guidance or mention of alternatives like list_services, find_available_services, or search_businesses.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
10 tool updates
- Added
cancel_booking - Added
create_booking - Changed
find_available_services3 fields changed- added
Input schema / properties / locationAdded value: +{ + "description": "Optional place text ('City, ST', ZIP, bare city/state) OR explicit coordinates 'lat,lng' — identical semantics to search_businesses.location.", + "maxLength": 120, + "type": "string" +} - added
Input schema / properties / radius_milesAdded value: +{ + "description": "Radius in miles (default 25) — operative when the location resolves to coordinates (2.6 semantics).", + "maximum": 500, + "minimum": 1, + "type": "integer" +} - changed
Output schema / anyOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "candidates": { - "items": { - "additionalProperties": false, - "properties": { - "checked": { - "description": "TRUE only when this candidate's availability was actually computed. FALSE means skipped (over budget, read failure, or per-tenant availability budget exhausted) — its earliest_slot is unknown, not absent.", - "type": "boolean" - }, - "demo": { - "type": "boolean" - }, - "demo_notice": { - "description": "Present on every demo candidate — relay it; never describe a demo business as a real provider.", - "type": "string" - }, - "earliest_slot": { - "additionalProperties": false, - "properties": { - "end_iso": { - "format": "date-time", - "type": "string" - }, - "start_iso": { - "format": "date-time", - "type": "string" - } - }, - "required": [ - "start_iso", - "end_iso" - ], - "type": [ - "object", - "null" - ] - }, - "location": { - "additionalProperties": false, - "properties": { - "city": { - "type": [ - "string", - "null" - ] - }, - "match": { - "description": "The coarse place relationship used for this result.", - "enum": [ - "postal", - "city", - "market", - "region" - ], - "type": "string" - }, - "postal_code": { - "type": [ - "string", - "null" - ] - }, - "region": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "match": { - "additionalProperties": false, - "properties": { - "evidence": { - "items": { - "type": "string" - }, - "type": "array" - }, - "match_type": { - "enum": [ - "exact", - "ontology", - "description" - ], - "type": "string" - }, - "score": { - "type": "integer" - } - }, - "required": [ - "score", - "match_type" - ], - "type": "object" - }, - "service": { - "additionalProperties": false, - "properties": { - "duration_minutes": { - "type": "integer" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "price_cents": { - "type": [ - "integer", - "null" - ] - }, - "price_label": { - "type": "string" - } - }, - "required": [ - "id", - "name" - ], - "type": "object" - }, - "tenant_name": { - "type": "string" - }, - "tenant_slug": { - "description": "Pass as tenantSlug (gateway) / tenant (MCP) to the tenant-scoped actions.", - "type": "string" - } - }, - "required": [ - "tenant_slug", - "tenant_name", - "demo", - "checked", - "service", - "match", - "earliest_slot" - ], - "type": "object" - }, - "type": "array" - }, - "demo_notice": { - "type": "string" - }, - "earliest_after": { - "description": "The exact window start used.", - "format": "date-time", - "type": "string" - }, - "earliest_before": { - "description": "The exact window end used.", - "format": "date-time", - "type": "string" - }, - "outcome": { - "enum": [ - "ok" - ], - "type": "string" - }, - "partial": { - "description": "TRUE whenever any candidate went unchecked OR more matched businesses existed than candidate_limit covered. When true, present the result as \"the earliest among the top N candidates checked\" — never \"the earliest anywhere\".", - "type": "boolean" - } - }, - "required": [ - "outcome", - "earliest_after", - "earliest_before", - "partial", - "candidates" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "detail": { - "description": "A short user-safe explanation.", - "type": "string" - }, - "outcome": { - "description": "A stable failure category.", - "enum": [ - "validation_error", - "rate_limited", - "internal_error" - ], - "type": "string" - }, - "reason": { - "description": "A stable machine-readable reason.", - "type": "string" - }, - "retry_after_sec": { - "minimum": 1, - "type": "integer" - } - }, - "required": [ - "outcome", - "reason", - "detail" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "candidates": { + "items": { + "additionalProperties": false, + "properties": { + "checked": { + "type": "boolean" + }, + "demo": { + "type": "boolean" + }, + "demo_notice": { + "type": "string" + }, + "earliest_slot": { + "additionalProperties": false, + "properties": { + "end_iso": { + "format": "date-time", + "type": "string" + }, + "start_iso": { + "format": "date-time", + "type": "string" + } + }, + "type": [ + "object", + "null" + ] + }, + "location": { + "additionalProperties": false, + "properties": { + "city": { + "type": [ + "string", + "null" + ] + }, + "distance_miles": { + "type": "number" + }, + "match": { + "enum": [ + "postal", + "city", + "market", + "region", + "coordinates" + ], + "type": "string" + }, + "postal_code": { + "type": [ + "string", + "null" + ] + }, + "region": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "match": { + "additionalProperties": false, + "properties": { + "evidence": { + "items": { + "type": "string" + }, + "type": "array" + }, + "match_type": { + "enum": [ + "exact", + "ontology", + "description" + ], + "type": "string" + }, + "score": { + "type": "integer" + } + }, + "type": "object" + }, + "service": { + "additionalProperties": false, + "properties": { + "duration_minutes": { + "type": "integer" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "price_cents": { + "type": [ + "integer", + "null" + ] + }, + "price_label": { + "type": "string" + } + }, + "type": "object" + }, + "tenant_name": { + "type": "string" + }, + "tenant_slug": { + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "demo_businesses_excluded": { + "minimum": 1, + "type": "integer" + }, + "demo_businesses_excluded_is_exhaustive": { + "type": "boolean" + }, + "demo_exclusion_note": { + "type": "string" + }, + "demo_notice": { + "type": "string" + }, + "distance_note": { + "type": "string" + }, + "earliest_after": { + "format": "date-time", + "type": "string" + }, + "earliest_before": { + "format": "date-time", + "type": "string" + }, + "outcome": { + "const": "ok" + }, + "partial": { + "type": "boolean" + } + }, + "required": [ + "outcome", + "earliest_after", + "earliest_before", + "partial", + "candidates" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "detail": { + "type": "string" + }, + "outcome": { + "enum": [ + "validation_error", + "rate_limited", + "internal_error" + ], + "type": "string" + }, + "reason": { + "type": "string" + }, + "retry_after_sec": { + "type": "integer" + } + }, + "required": [ + "outcome", + "reason", + "detail" + ], + "type": "object" + } +]
- Changed
get_availability2 fields changed- removed
Input schema / properties / date_range / descriptionRemoved value: -"Exact YYYY-MM-DD start and end dates, spanning no more than 31 days." - changed
Output schema / anyOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "outcome": { - "enum": [ - "ok" - ], - "type": "string" - }, - "slots": { - "items": { - "additionalProperties": false, - "properties": { - "end_iso": { - "format": "date-time", - "type": "string" - }, - "provider_id": { - "type": "string" - }, - "provider_name": { - "type": "string" - }, - "start_iso": { - "format": "date-time", - "type": "string" - } - }, - "required": [ - "start_iso", - "end_iso", - "provider_id" - ], - "type": "object" - }, - "maxItems": 20, - "type": "array" - }, - "timezone": { - "type": "string" - } - }, - "required": [ - "outcome", - "timezone", - "slots" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "detail": { - "description": "A short user-safe explanation.", - "type": "string" - }, - "outcome": { - "description": "A stable failure category.", - "enum": [ - "validation_error", - "rate_limited", - "internal_error" - ], - "type": "string" - }, - "reason": { - "description": "A stable machine-readable reason.", - "type": "string" - }, - "retry_after_sec": { - "minimum": 1, - "type": "integer" - } - }, - "required": [ - "outcome", - "reason", - "detail" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "bookable": { + "type": "boolean" + }, + "booking_mode": { + "enum": [ + "instant", + "approval_required" + ], + "type": "string" + }, + "notice": { + "type": "string" + }, + "outcome": { + "enum": [ + "ok" + ], + "type": "string" + }, + "slots": { + "items": { + "additionalProperties": false, + "properties": { + "end_iso": { + "format": "date-time", + "type": "string" + }, + "provider_id": { + "type": "string" + }, + "provider_name": { + "type": "string" + }, + "start_iso": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "start_iso", + "end_iso", + "provider_id" + ], + "type": "object" + }, + "maxItems": 20, + "type": "array" + }, + "status_reason": { + "enum": [ + "suspended", + "agent_booking_disabled", + "no_booking_section" + ], + "type": "string" + }, + "timezone": { + "type": "string" + } + }, + "required": [ + "outcome", + "timezone", + "slots" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "detail": { + "type": "string" + }, + "outcome": { + "enum": [ + "validation_error", + "rate_limited", + "internal_error" + ], + "type": "string" + }, + "reason": { + "type": "string" + }, + "retry_after_sec": { + "type": "integer" + } + }, + "required": [ + "outcome", + "reason", + "detail" + ], + "type": "object" + } +]
- Added
get_booking_status - Added
get_reschedule_options - Changed
list_services1 field changed- changed
Output schema / anyOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "outcome": { - "enum": [ - "ok" - ], - "type": "string" - }, - "providers": { - "items": { - "additionalProperties": false, - "properties": { - "bio": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "service_ids": { - "description": "The catalog service ids this provider performs (expanded — never empty for an active provider).", - "items": { - "type": "string" - }, - "type": "array" - } - }, - "required": [ - "id", - "name", - "service_ids" - ], - "type": "object" - }, - "type": "array" - }, - "services": { - "items": { - "additionalProperties": false, - "properties": { - "description": { - "type": "string" - }, - "duration_minutes": { - "type": "integer" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "price_cents": { - "description": "Parsed price in cents; null when the configured free-text price is unparseable.", - "type": [ - "integer", - "null" - ] - }, - "price_label": { - "description": "The raw configured price text.", - "type": "string" - } - }, - "required": [ - "id", - "name", - "duration_minutes", - "price_cents", - "price_label" - ], - "type": "object" - }, - "type": "array" - }, - "tenant": { - "additionalProperties": false, - "properties": { - "name": { - "type": "string" - }, - "timezone": { - "description": "IANA zone the schedule is expressed in; empty string when unset (UTC semantics).", - "type": "string" - } - }, - "required": [ - "name", - "timezone" - ], - "type": "object" - } - }, - "required": [ - "outcome", - "tenant", - "services", - "providers" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "detail": { - "description": "A short user-safe explanation.", - "type": "string" - }, - "outcome": { - "description": "A stable failure category.", - "enum": [ - "validation_error", - "rate_limited", - "internal_error" - ], - "type": "string" - }, - "reason": { - "description": "A stable machine-readable reason.", - "type": "string" - }, - "retry_after_sec": { - "minimum": 1, - "type": "integer" - } - }, - "required": [ - "outcome", - "reason", - "detail" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "outcome": { + "enum": [ + "ok" + ], + "type": "string" + }, + "providers": { + "items": { + "additionalProperties": false, + "properties": { + "bio": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "service_ids": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "id", + "service_ids" + ], + "type": "object" + }, + "type": "array" + }, + "services": { + "items": { + "additionalProperties": false, + "properties": { + "add_ons": { + "items": { + "additionalProperties": false, + "properties": { + "duration_minutes": { + "type": "integer" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "price_cents": { + "type": "integer" + } + }, + "type": "object" + }, + "type": "array" + }, + "deposit_cents": { + "type": "integer" + }, + "duration_minutes": { + "type": "integer" + }, + "id": { + "type": "string" + }, + "intake_form": { + "allOf": [ + { + "additionalProperties": false, + "properties": { + "fields": { + "items": { + "additionalProperties": false, + "properties": { + "consent": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "options": { + "items": { + "type": "string" + }, + "type": "array" + }, + "required": { + "type": "boolean" + }, + "type": { + "enum": [ + "text", + "textarea", + "boolean", + "select", + "date" + ], + "type": "string" + } + }, + "required": [ + "id", + "label", + "type", + "required" + ], + "type": "object" + }, + "type": "array" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "required": { + "type": "boolean" + } + }, + "required": [ + "id", + "name", + "required", + "fields" + ], + "type": "object" + } + ] + }, + "intake_required": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "price_cents": { + "type": [ + "integer", + "null" + ] + }, + "price_label": { + "type": "string" + } + }, + "required": [ + "id", + "name", + "duration_minutes", + "price_label" + ], + "type": "object" + }, + "type": "array" + }, + "tenant": { + "additionalProperties": false, + "properties": { + "capabilities": { + "additionalProperties": false, + "properties": { + "add_ons": { + "type": "boolean" + }, + "agent_booking": { + "type": "boolean" + }, + "bookable": { + "type": "boolean" + }, + "booking_mode": { + "enum": [ + "instant", + "approval_required", + "external_booking_mode" + ], + "type": "string" + }, + "deposits": { + "type": "boolean" + }, + "intake": { + "type": "boolean" + }, + "multi_service": { + "type": "boolean" + }, + "native_booking": { + "type": "boolean" + }, + "provider_selection": { + "type": "boolean" + }, + "status_reason": { + "enum": [ + "suspended", + "agent_booking_disabled", + "no_booking_section" + ], + "type": "string" + } + }, + "required": [ + "native_booking", + "booking_mode", + "bookable" + ], + "type": "object" + }, + "name": { + "type": "string" + }, + "timezone": { + "type": "string" + } + }, + "required": [ + "name", + "capabilities" + ], + "type": "object" + } + }, + "required": [ + "outcome", + "tenant", + "services", + "providers" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "detail": { + "type": "string" + }, + "outcome": { + "enum": [ + "validation_error", + "rate_limited", + "internal_error" + ], + "type": "string" + }, + "reason": { + "type": "string" + }, + "retry_after_sec": { + "type": "integer" + } + }, + "required": [ + "outcome", + "reason", + "detail" + ], + "type": "object" + } +]
- Added
reschedule_booking - Changed
search_businesses3 fields changed- added
Input schema / properties / locationAdded value: +{ + "description": "Optional place text ('City, ST', ZIP, bare city/state) OR explicit coordinates 'lat,lng'. With resolvable coordinates, radius_miles applies as real distance; otherwise matching is city/ZIP/metro-market text equality.", + "maxLength": 120, + "type": "string" +} - added
Input schema / properties / radius_milesAdded value: +{ + "description": "Radius in miles (default 25) — OPERATIVE when the location resolves to coordinates (2.6); otherwise answered with a truthful distance_note instead of a fabricated distance.", + "maximum": 500, + "minimum": 1, + "type": "integer" +} - changed
Output schema / anyOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "businesses": { - "items": { - "additionalProperties": false, - "properties": { - "agent_address": { - "description": "Canonical public Kirah Agent Address for this business when its authoritative domain is a safe single-label *.kirah.ai domain. Locator only; never authentication. Absent for custom domains and reserved/invalid handles in migration-free v1.", - "type": "string" - }, - "agent_bookable": { - "type": "boolean" - }, - "agent_discoverable": { - "description": "Present for V1-enrolled tenants; true because the row passed current owner discovery consent.", - "type": "boolean" - }, - "authority_mode": { - "description": "Present for V1-enrolled tenants; null when discoverable but not agent-bookable.", - "enum": [ - "instant", - "approval_required", - null - ], - "type": [ - "string", - "null" - ] - }, - "demo": { - "description": "true = a DEMONSTRATION business (present on every result; demo results also carry demo_notice).", - "type": "boolean" - }, - "demo_notice": { - "type": "string" - }, - "location": { - "additionalProperties": false, - "properties": { - "city": { - "type": [ - "string", - "null" - ] - }, - "match": { - "description": "The coarse place relationship used for this result.", - "enum": [ - "postal", - "city", - "market", - "region" - ], - "type": "string" - }, - "postal_code": { - "type": [ - "string", - "null" - ] - }, - "region": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "matched_services": { - "items": { - "additionalProperties": false, - "properties": { - "duration_minutes": { - "type": "integer" - }, - "id": { - "type": "string" - }, - "match_evidence": { - "description": "Grounded explanations (which query/ontology terms matched which catalog text).", - "items": { - "type": "string" - }, - "maxItems": 4, - "type": "array" - }, - "match_type": { - "description": "exact = a direct query term matched the service name or category. ontology = only a discovery-ontology expansion term matched the name or description. description = a direct query term matched ONLY the description. Ranking always tiers exact above ontology above description, regardless of score — a service whose description merely mentions a term never outranks a service actually named for it.", - "enum": [ - "exact", - "ontology", - "description" - ], - "type": "string" - }, - "name": { - "type": "string" - }, - "price_cents": { - "type": [ - "integer", - "null" - ] - }, - "price_label": { - "type": "string" - } - }, - "required": [ - "id", - "name", - "match_type" - ], - "type": "object" - }, - "maxItems": 3, - "minItems": 0, - "type": "array" - }, - "score": { - "description": "The tenant's top matched service's integer score — used for cross-business ranking together with match_type tier. Zero in exact agent_address resolution mode when matched_services is empty.", - "type": "integer" - }, - "service_match": { - "description": "True when matched_services contains a grounded query match. False only for exact agent_address resolution with no matching/supplied service query.", - "type": "boolean" - }, - "tenant_name": { - "type": "string" - }, - "tenant_slug": { - "description": "The stable identifier for every tenant-scoped action (the tenant's full domain).", - "type": "string" - } - }, - "required": [ - "tenant_slug", - "tenant_name", - "demo", - "score", - "service_match", - "matched_services" - ], - "type": "object" - }, - "type": "array" - }, - "demo_notice": { - "description": "Present when any demo result is included.", - "type": "string" - }, - "is_exhaustive": { - "description": "True only when the roster scan did not hit its internal candidate cap AND every matching tenant (from any cursor position forward) fit within this page. NEVER fabricated: hitting the roster cap always yields false, even with no cursor and few matches.", - "type": "boolean" - }, - "location_precision": { - "description": "The public surface reports coarse matching precision only.", - "enum": [ - "city_zip_market", - "none" - ], - "type": "string" - }, - "next_cursor": { - "description": "Present only when more matching tenants exist beyond this page. Opaque; pass back verbatim as `cursor` with the SAME query/filters to resume.", - "type": "string" - }, - "outcome": { - "enum": [ - "ok" - ], - "type": "string" - }, - "resolution": { - "additionalProperties": false, - "properties": { - "agent_address": { - "type": "string" - }, - "exact": { - "enum": [ - true - ], - "type": "boolean" - }, - "found": { - "type": "boolean" - }, - "type": { - "enum": [ - "agent_address" - ], - "type": "string" - } - }, - "required": [ - "type", - "agent_address", - "exact", - "found" - ], - "type": "object" - } - }, - "required": [ - "outcome", - "location_precision", - "businesses", - "is_exhaustive" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "detail": { - "description": "A short user-safe explanation.", - "type": "string" - }, - "outcome": { - "description": "A stable failure category.", - "enum": [ - "validation_error", - "rate_limited", - "internal_error" - ], - "type": "string" - }, - "reason": { - "description": "A stable machine-readable reason.", - "type": "string" - }, - "retry_after_sec": { - "minimum": 1, - "type": "integer" - } - }, - "required": [ - "outcome", - "reason", - "detail" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "businesses": { + "items": { + "additionalProperties": false, + "properties": { + "agent_address": { + "type": "string" + }, + "agent_bookable": { + "type": "boolean" + }, + "agent_discoverable": { + "type": "boolean" + }, + "authority_mode": { + "enum": [ + "instant", + "approval_required", + null + ], + "type": [ + "string", + "null" + ] + }, + "demo": { + "type": "boolean" + }, + "demo_notice": { + "type": "string" + }, + "listed": { + "enum": [ + true + ], + "type": "boolean" + }, + "location": { + "additionalProperties": false, + "properties": { + "city": { + "type": [ + "string", + "null" + ] + }, + "distance_miles": { + "type": "number" + }, + "match": { + "enum": [ + "postal", + "city", + "market", + "region", + "coordinates" + ], + "type": "string" + }, + "postal_code": { + "type": [ + "string", + "null" + ] + }, + "region": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "matched_services": { + "items": { + "additionalProperties": false, + "properties": { + "duration_minutes": { + "type": "integer" + }, + "id": { + "type": "string" + }, + "match_evidence": { + "items": { + "type": "string" + }, + "maxItems": 4, + "type": "array" + }, + "match_type": { + "enum": [ + "exact", + "ontology", + "description" + ], + "type": "string" + }, + "name": { + "type": "string" + }, + "price_cents": { + "type": [ + "integer", + "null" + ] + }, + "price_label": { + "type": "string" + } + }, + "required": [ + "id", + "name", + "match_type" + ], + "type": "object" + }, + "maxItems": 3, + "minItems": 0, + "type": "array" + }, + "resolution": { + "enum": [ + "exact_agent_address" + ], + "type": "string" + }, + "score": { + "type": "integer" + }, + "service_match": { + "type": "boolean" + }, + "tenant_name": { + "type": "string" + }, + "tenant_slug": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "required": [ + "tenant_slug", + "tenant_name", + "demo", + "listed", + "matched_services", + "score", + "service_match", + "agent_bookable" + ], + "type": "object" + }, + "maxItems": 10, + "type": "array" + }, + "demo_businesses_excluded": { + "minimum": 1, + "type": "integer" + }, + "demo_businesses_excluded_is_exhaustive": { + "type": "boolean" + }, + "demo_exclusion_note": { + "type": "string" + }, + "demo_notice": { + "type": "string" + }, + "distance_note": { + "type": "string" + }, + "is_exhaustive": { + "type": "boolean" + }, + "location_precision": { + "enum": [ + "coordinates", + "city_zip_market", + "none" + ], + "type": "string" + }, + "next_cursor": { + "type": "string" + }, + "outcome": { + "enum": [ + "ok" + ], + "type": "string" + }, + "resolution": { + "additionalProperties": false, + "properties": { + "agent_address": { + "type": "string" + }, + "exact": { + "enum": [ + true + ], + "type": "boolean" + }, + "found": { + "type": "boolean" + }, + "type": { + "enum": [ + "agent_address" + ], + "type": "string" + } + }, + "required": [ + "type", + "agent_address", + "exact", + "found" + ], + "type": "object" + } + }, + "required": [ + "outcome", + "location_precision", + "businesses", + "is_exhaustive" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "detail": { + "type": "string" + }, + "outcome": { + "enum": [ + "validation_error", + "rate_limited", + "internal_error" + ], + "type": "string" + }, + "reason": { + "type": "string" + }, + "retry_after_sec": { + "type": "integer" + } + }, + "required": [ + "outcome", + "reason", + "detail" + ], + "type": "object" + } +]
- Changed
search_services1 field changed- changed
Output schema / anyOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "candidates": { - "items": { - "additionalProperties": false, - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "score": { - "type": "number" - } - }, - "required": [ - "id", - "name", - "score" - ], - "type": "object" - }, - "maxItems": 5, - "type": "array" - }, - "outcome": { - "enum": [ - "ok" - ], - "type": "string" - } - }, - "required": [ - "outcome", - "candidates" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "detail": { - "description": "A short user-safe explanation.", - "type": "string" - }, - "outcome": { - "description": "A stable failure category.", - "enum": [ - "validation_error", - "rate_limited", - "internal_error" - ], - "type": "string" - }, - "reason": { - "description": "A stable machine-readable reason.", - "type": "string" - }, - "retry_after_sec": { - "minimum": 1, - "type": "integer" - } - }, - "required": [ - "outcome", - "reason", - "detail" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "candidates": { + "items": { + "additionalProperties": false, + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "score": { + "type": "number" + } + }, + "required": [ + "id", + "name", + "score" + ], + "type": "object" + }, + "maxItems": 5, + "type": "array" + }, + "outcome": { + "enum": [ + "ok" + ], + "type": "string" + } + }, + "required": [ + "outcome", + "candidates" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "detail": { + "type": "string" + }, + "outcome": { + "enum": [ + "validation_error", + "rate_limited", + "internal_error" + ], + "type": "string" + }, + "reason": { + "type": "string" + }, + "retry_after_sec": { + "type": "integer" + } + }, + "required": [ + "outcome", + "reason", + "detail" + ], + "type": "object" + } +]
5 tool updates
- First observed
find_available_services - First observed
get_availability - First observed
list_services - First observed
search_businesses - First observed
search_services
Related MCP Connectors
Find local services, check live availability, and book real appointments with consent.
Find participating local service providers and book live appointment times.
Find local services, read availability, and create short-lived booking holds.
Search and book appointments at local businesses. Barbershops, salons, spas, and more.
Related MCP Servers
- AlicenseAqualityAmaintenanceBook a table, an appointment or a place in a class at a real local business. Live availability, instant confirmation, no account and no API key. Eight tools: search, fetch, get_business, check_availability, create_booking, check_booking, cancel_booking and request_listing. Guest emails in eight languages. Hosted at https://g-guest.app/api/mcp8131 npmMIT

@qasperai/mcp-serverofficial
AlicenseAqualityCmaintenanceEnables AI assistants to discover and book local service businesses like barbers, plumbers, and mechanics directly through MCP-compatible tools.945 npmMIT- AlicenseNot gradedqualityCmaintenanceEnables AI agents to search for businesses, check availability and pricing, and book appointments after user confirmation through trusted WebMCP tools.912 npmMIT
- FlicenseNot gradedqualityDmaintenanceEnables users to query real-time reservation availability for Naver Booking places in Korea, including beauty salons, restaurants, and other categories.-
Glama MCP Gateway
Add one secure layer between your agents and this server.