Center

Center booking connector

One public MCP server for personal AI assistants. An assistant uses it to help the person who asked, and books only once that person approves.

What it does

  • Finds businesses published on Center.
  • Answers questions from a business's public facts only.
  • Checks open times.
  • Books for the signed-in person, with their approval.

It is separate from the person's own Center errands server.

Endpoint and discovery

https://app.center.com/mcp

Streamable HTTP: one JSON-RPC message per POST, as application/json. GET and DELETE answer 405.

WhatWhere
MCP endpointhttps://app.center.com/mcp
Protected-resource metadata (RFC 9728)https://app.center.com/.well-known/oauth-protected-resource
Protected-resource metadata (RFC 9728)https://app.center.com/.well-known/oauth-protected-resource/mcp
Authorization-server metadata (RFC 8414), issuer https://app.center.comhttps://app.center.com/.well-known/oauth-authorization-server
Authorization endpoint (consent page, English and Spanish)https://app.center.com/connect/authorize
Dynamic client registration (RFC 7591)https://app.center.com/v1/platform/connector/oauth/register
Tokenhttps://app.center.com/v1/platform/connector/oauth/token
Revocation (RFC 7009)https://app.center.com/v1/platform/connector/oauth/revoke

Authorization (OAuth 2.1)

  1. With no bearer token, POST /mcp answers 401 with a WWW-Authenticate challenge that names the protected-resource metadata and the scopes.
  2. The assistant reads the discovery documents and registers itself. Clients are public only (token_endpoint_auth_method: none). Redirects must be https, or http on loopback; they match exactly, and a loopback redirect may use any port.
  3. The person opens the consent page. The request must carry code_challenge with code_challenge_method=S256 (PKCE S256 is required; plain is refused), state and resource. When resource is present it must be https://app.center.com/mcp.
  4. The person signs in with a one-time code sent by text to their phone. Email sign-in is not available yet.
  5. The consent page names the assistant (as it registered itself), the scopes, and exactly what a business receives when the person books. The person chooses Allow or Don’t allow.
  6. A single-use code (10 minutes) returns with state and iss (RFC 9207). The token exchange checks the PKCE verifier and returns an access token (1 hour) and a refresh token (60 days). Refresh tokens rotate on every use; reusing an old one revokes the whole link. Tokens are bound to https://app.center.com/mcp.

Credentials are opaque. Center stores only their SHA-256 digests.

Scopes

ScopeTools
businesses.readsearch_businesses, get_business, find_available_slots, ask_business
bookings.writeprepare_booking, confirm_booking, get_booking_status, cancel_booking, reschedule_booking

Any signed-in person may use the read tools. A booking tool called without bookings.write gets HTTP 403 insufficient_scope and a step-up challenge.

Tools

The connector only sees published businesses. Each result is built field by field from the public record.

search_businesses

Read or write
Read (businesses.read)
Returns
Published, indexable, real businesses only. For each: id, handle, name, category, city, rating summary, price range, top services (price and duration), whether online booking is supported, and the site URL.
Side effects
None.
Annotations
readOnlyHint: yes, destructiveHint: no, idempotentHint: yes, openWorldHint: no
FieldTypeMeaning
querystringWhat the person is looking for.
nearstring (city) | {lat, lng}A city, or a point.
category (optional)stringA kind of business.
when (optional)date or date-timeWhen the person wants to go.
max_price (optional)numberHighest price, in whole currency units.
language (optional)'en' or 'es'The language of the answer.

get_business

Read or write
Read (businesses.read)
Returns
The public profile: services with price and duration, hours, address, phone, policies (deposit and cancellation), amenities, languages, showcased reviews (4★ and up), and photo URLs.
Side effects
None.
Annotations
readOnlyHint: yes, destructiveHint: no, idempotentHint: yes, openWorldHint: no
FieldTypeMeaning
business_idstringThe business, from search_businesses.

find_available_slots

Read or write
Read (businesses.read)
Returns
Open times, each with the current price, in the business's time zone. Never who holds any other time.
Side effects
None.
Annotations
readOnlyHint: yes, destructiveHint: no, idempotentHint: no, openWorldHint: no
FieldTypeMeaning
business_idstringThe business.
service_idstringThe service.
fromdate or date-timeStart of the window.
todate or date-timeEnd of the window.
party (optional)integerHow many people.

ask_business

Read or write
Read (businesses.read)
Returns
An answer written only from the business's published facts, in the language of the question. It says when it does not know.
Side effects
None.
Annotations
readOnlyHint: yes, destructiveHint: no, idempotentHint: no, openWorldHint: no
FieldTypeMeaning
business_idstringThe business.
questionstringThe question, in any language.

prepare_booking

Read or write
Write (holds one time) (bookings.write)
Returns
A proposal: proposal_id, the exact service, the time in the business's time zone, the total, the policies, what the business will receive (name and phone), expires_at, and the words of the confirmation-text consent.
Side effects
A 5-minute hold on the time that nobody else can see. One person holds at most one time per business; a new proposal at the same business replaces the earlier hold.
Annotations
readOnlyHint: no, destructiveHint: no, idempotentHint: no, openWorldHint: no
FieldTypeMeaning
business_idstringThe business.
service_idstringThe service.
startdate-timeThe chosen time.
notes (optional)stringA note for the business.

confirm_booking

Read or write
Write (bookings.write)
Returns
A stable booking_ref, the time and the status.
Side effects
Books through the business's own booking, which notifies the business as for any booking on its site. Repeating the call answers the same booking.
Annotations
readOnlyHint: no, destructiveHint: no, idempotentHint: yes, openWorldHint: no
FieldTypeMeaning
proposal_idstringFrom prepare_booking.
texts_consentbooleanWhether the person agreed to the confirmation texts, in the words prepare_booking returned.

get_booking_status

Read or write
Read (own booking) (bookings.write)
Returns
Status, service, time, business, and whether it can still be changed.
Side effects
None.
Annotations
readOnlyHint: yes, destructiveHint: no, idempotentHint: yes, openWorldHint: no
FieldTypeMeaning
booking_refstringFrom confirm_booking.

cancel_booking

Read or write
Write (bookings.write)
Returns
The cancelled status.
Side effects
Cancels the booking, within the business's own cancellation cutoff.
Annotations
readOnlyHint: no, destructiveHint: yes, idempotentHint: yes, openWorldHint: no
FieldTypeMeaning
booking_refstringFrom confirm_booking.
reason (optional)stringWhy, for the business.

reschedule_booking

Read or write
Write (bookings.write)
Returns
The moved time.
Side effects
Moves the booking. Same service, same staff.
Annotations
readOnlyHint: no, destructiveHint: yes, idempotentHint: no, openWorldHint: no
FieldTypeMeaning
booking_refstringFrom confirm_booking.
new_startdate-timeThe new time.

A price is stated only when the owner confirmed it or it comes from the business's own public page. Any other price reads "price not published", never $0. A business with nothing bookable online returns booking_supported: false with how to book (its booking or reservation link and its phone).

Deposits

The connector does not take payments, and money never moves through an assistant. When a service collects a deposit or the full price at booking, prepare_booking refuses with deposit_required. The refusal carries the deposit amount when it is published, plus the business's booking page and phone. Nothing is held, and nothing is booked without the deposit the business requires.

Errors

  • No valid token: HTTP 401 with the RFC 9728 challenge (WWW-Authenticate: Bearer resource_metadata=…, scope=…).
  • Missing scope: HTTP 403 insufficient_scope.
  • Past a rate limit: HTTP 429 with Retry-After, and a JSON-RPC error whose data is {error: 'rate_limited', retry_after_seconds}.
  • A tool refusal is a tool result with isError: true and structuredContent: {error: <reason>, message, …}.

Reasons:

  • invalid_arguments
  • business_not_found
  • service_not_found
  • service_not_bookable_online
  • booking_not_supported
  • deposit_required
  • slot_unavailable
  • proposal_not_found
  • proposal_expired
  • terms_changed
  • booking_not_found
  • cancel_window_passed
  • already_cancelled
  • test_account_real_business
  • booking_unavailable
  • ask_unavailable

Rate limits

Per minute:

WhoReadsask_businessprepare_bookingEach booking write
Per person6010105
Per client3000300300150

Each address may make up to 600 requests a minute to /mcp, because assistants call from shared addresses.

Privacy

  • Facts come only from a business's public record. No tool reads a business's clients, bookings or conversations.
  • Times are open times only: the connector never says who holds another time, never names another client, and never gives a staff member's private details.
  • A person sees, cancels and moves only the bookings they made through the connector. Anyone else's booking reads booking_not_found.

When the person books, the business receives the name on their Center account and their verified phone. The consent page says so before they allow access.

Support and policies

Questions or problems: help@center.com