Browse the manual

Visitor door for visitors' AI clients

The public MCP and HTTP door that lets a visitor's own AI client read published widgets and website pages and act as that visitor.

On this page

The visitor door lets a visitor's own AI client do on a business's widgets and website what that visitor can do by hand. It needs no account, no key and no person at the business. This page is for developers who build or test such a client.

The visitor door is a separate public door. It has nothing in common with the staff door at /mcp and /api/v1 that AI connections use:

Staff door Visitor door
Who calls it A client acting for a staff member Any client, acting as a visitor
Address /mcp and /api/v1 /visitor/mcp and /visitor/v1
Credential A connection credential or OAuth token None. A visitor_token argument for signed-in acts
Default Off until the owner connects a client On; the owner can turn it off
Reaches The delegated person's records and tools Published widgets and website pages only
Approvals Sensitive steps need the delegated person's approval None. Visitor acts follow the form's own rules

A staff connection never lists a visitor tool, and a visitor call never reaches a staff tool, a staff record or a customer account. A staff credential sent to the visitor door is ignored. The steps that stay with people still have no staff tool. A visitor's own client performs them here as that visitor.

Find the endpoint

All addresses are on the installation's own address, for example https://office.example.com:

Path Purpose
POST /visitor/mcp The MCP endpoint
GET /visitor/v1/tools The tool list over HTTP, 50 tools per page with a cursor
POST /visitor/v1/{tool} One tool over HTTP, with a JSON object body
GET /visitor/v1/{tool} A read tool that needs no sign-in, with the arguments as query parameters
GET /.well-known/mcp-server-card The server card

A website on a custom domain does not serve these paths. Its llms.txt names the installation's absolute address. The owner sees the addresses under Settings > Widgets > Address for agents.

The server card follows the MCP server card proposal SEP-2127, which is a draft. It holds the schema, a name, the version, the business name as the title, a fixed description and one streamable-http remote with the supported protocol versions. The path changes only if the MCP specification adopts another one.

A published widget page links its machine-readable version (rel="alternate", /visitor/v1/widgets.read?key={key}) and the server card (rel="service-desc"). A website's llms.txt lists its indexable widgets and ends with the MCP endpoint.

Call over MCP

The door follows the MCP specification release 2026-07-28 and accepts the earlier releases.

  • A 2026-07-28 request is stateless. Send the MCP-Protocol-Version, Mcp-Method and, for tools/call, Mcp-Name headers with the same values as the body. A mismatch answers 400 with code -32020.
  • initialize selects 2025-11-25, 2025-06-18 or 2025-03-26. The door creates no session.
  • The methods are server/discover, tools/list, tools/call and ping. tools/list returns 50 tools per page with a cursor.
  • Every answer is one application/json reply, never a stream. A notification answers 202. A batch answers 400. GET and DELETE on /visitor/mcp answer 405.
  • A read tool has readOnlyHint: true. An act has readOnlyHint: false, destructiveHint: false and idempotentHint: true.
  • A result is structuredContent plus one text block with the same JSON. A failure has isError: true and the same {error} object as HTTP.

The MCP name of a tool is its key with dots replaced by underscores: visitor.widgets.read is visitor_widgets_read.

Call over HTTP

The HTTP path segment is the key without visitor.:

POST /visitor/v1/widgets.read
Content-Type: application/json

{"key": "<64-character widget key from /w/{key}>"}

A read tool without sign-in also answers GET /visitor/v1/widgets.read?key=…. HEAD works like GET for these read tools and answers without a body. GET or HEAD on an act answers 405 method_not_allowed. Never put a visitor_token in a query string. The door refuses it with validation_failed.

Rules for every request

  • The door uses no cookie and no session. It removes Authorization and Cookie before it reads the request, and it never sends Set-Cookie.
  • Every answer has Cache-Control: no-store and X-Robots-Tag: noindex.
  • A body is a JSON object of at most 64 KiB. Another content type answers 415. A larger body answers 413.
  • JSON can nest at most 64 levels deep. A deeper body answers 400 invalid_request, or JSON-RPC error -32600 on MCP. The door runs no tool for it.
  • Send no Origin header. An Origin other than the installation's own answers 403 origin_refused. The door grants no CORS access.
  • An error is {"error": {"code", "message", "fields"}}. The message is translated text without debug detail. fields appears for invalid input.
Limit Value When exceeded
Reads 60 a minute per IP address 429 with Retry-After and retry_after
Acts 10 a minute and 100 an hour per IP address 429 with Retry-After and retry_after
Calls with one visitor_token 30 a minute 429 with Retry-After and retry_after
tools/list and GET /visitor/v1/tools 50 tools per page Use the cursor

Read, then act

  1. Call visitor.door.describe to see the business, the open widget families and the number of tools.
  2. Call visitor.widgets.read with the widget key. The answer holds the content, the version, the consent text and the tools for that widget.
  3. Call the act with the same version, the visitor's values and a new idempotency_key.

Every act needs an idempotency_key of 16 to 80 letters, digits, hyphens or underscores. Use a new key for each act. The same key with the same arguments returns the first receipt and creates nothing again. The same key with other arguments answers 409 idempotency_conflict. Pepper keeps keys for 24 hours.

If the business changed the widget or its consent text, the act answers 409 stale_version. Read the widget again and send the current version.

Sign in as the visitor

Some acts need the visitor's email code, as on the page: claiming an offer, joining a stamp card, a stock or listing alert, a waitlist place, subscribing to updates and the visitor's own proofs.

  1. Make a random verifier of 43 to 128 characters and keep it.
  2. Call visitor.sign_in.request with the widget key, the visitor's own email, a proof and an idempotency_key. The proof is the lowercase hex SHA-256 of the verifier.
  3. Ask the visitor for the six-digit code from their email.
  4. Call visitor.sign_in.verify with the key, the request ID, the code and the verifier.
  5. Send the returned token as the visitor_token argument to the signed-in tools of that widget.
  6. Call visitor.sign_in.end when the visitor is done.

The code is valid for 5 minutes, works once and allows 5 attempts. The answer to a code request is the same for every address. The token is valid for 15 minutes for one widget only. It never opens another widget, a staff account or a customer account.

The token travels only as the visitor_token argument, never as a header, cookie or query parameter.

A booking needs no email code, because the booking form needs none. It takes the same details and policy acceptance as the form.

Visitor tools

The list in an installation shows only the tools of open families. Each tool's input and output schema comes with tools/list and GET /visitor/v1/tools. Sign-in marks a tool that needs a visitor_token.

The door, pages and codes

Visitor tool Kind What it does
visitor.door.describe Read The business, the open families and the number of tools
visitor.widgets.read Read A published widget: content, version, consent text, notices, URLs and its tools
visitor.launchers.read Read A launcher's menu and the address of each widget in it
visitor.site.page_read Read A published website page in one language: text, facts and the widgets on it
visitor.placement.resolve Read Where a printed or shared code leads
visitor.sign_in.request Act Send a sign-in code to the visitor's email
visitor.sign_in.verify Act Exchange the code for a visitor_token
visitor.sign_in.end Act, sign-in End the sign-in

visitor.placement.resolve takes the 24-character key from a /p/{key} address. It returns the kind and the address. A Wi-Fi or contact code returns only its kind with encoded: true, never its content. A closed code returns its fallback address. The call counts as an agent read, never as a scan.

Forms, surveys and reviews

Visitor tool Kind What it does
visitor.forms.submit Act Send a form widget
visitor.forms.link_read Read Read a published form link: fields, version and branding
visitor.forms.link_submit Act Send a published form link
visitor.surveys.context Read The questions of an open survey or poll
visitor.surveys.submit Act Answer a survey or poll
visitor.reviews.submit Act Send a testimonial or feedback with the invitation from its email
visitor.reviews.withdraw Act Withdraw a testimonial with the token from its withdrawal address
Visitor tool Kind What it does
visitor.menus.estimate Read Calculate an estimate or check a menu request. Nothing is sent
visitor.menus.area Read Check whether the business serves a postal code
visitor.menus.request Act Send a menu, catering, estimate or service-area request
visitor.menus.quote_request Act Ask for a quote from a price list
visitor.shops.cart Act Create a cart, add lines and get a quote. It returns checkout_url, which the visitor opens to sign in, order and pay
visitor.shops.stock_alert Act, sign-in Ask for an email when a variant is back in stock
visitor.shops.stock_alert_withdraw Act Stop a stock alert with the token from its withdrawal address

Offers and stamp cards

Visitor tool Kind What it does
visitor.offers.claim Act, sign-in Claim an offer. Nothing is redeemed
visitor.offers.records Read, sign-in The visitor's own claims of this offer
visitor.offers.code Act, sign-in The code of the visitor's claim, to show at the counter
visitor.stamps.join Act, sign-in Join a stamp card
visitor.stamps.records Read, sign-in The visitor's own stamp cards
visitor.stamps.code Act, sign-in The code of the visitor's stamp card, to show at the counter

Bookings

Visitor tool Kind What it does
visitor.bookings.times Read Free times for a date and party size
visitor.bookings.quote Read The exact price and availability of one time
visitor.bookings.reserve Act Book a time with the form's details and policy acceptance
visitor.bookings.waitlist Act, sign-in Join the waitlist
visitor.bookings.visitor Read, sign-in Which email address is signed in for this booking widget

Listings

Visitor tool Kind What it does
visitor.listings.browse Read Published listings with filters and pages
visitor.listings.get Read One published listing
visitor.listings.request Act Send an enquiry, viewing request or application
visitor.listings.alert Act, sign-in Save a search and get an email for new listings
visitor.listings.alert_withdraw Act Stop a listing alert with the token from its unsubscribe address

Stories, proofs and contact cards

Visitor tool Kind What it does
visitor.stories.subscribe Act, sign-in Subscribe to update topics
visitor.stories.withdraw Act Unsubscribe, or withdraw a case-study consent, with the token from its address
visitor.stories.request Act Send a request from a case study or guide
visitor.proofs.read Read, sign-in The visitor's own proofs or job progress
visitor.proofs.decide Act, sign-in Approve a proof, select files, comment or ask for changes
visitor.proofs.answer Act, sign-in Answer a question about the visitor's job
visitor.proofs.preference Act, sign-in Turn stage emails on or off
visitor.proofs.quote Act, sign-in A short-lived link to the quote for the visitor's job
visitor.contacts.vcard Read A person's contact card as vCard text
visitor.contacts.message Act Send a message to a person from their business card

What the door does not do

  • Orders and card payments. The agent cannot place an order or pay. Each answer for a live cart carries checkout_url. That is the shop page with the cart in the address fragment. The visitor opens it, signs in to their customer account, places the order and enters card details at the payment provider. The place and payment steps answer 422 through the door.
  • Uploads. A form with a file field answers 422 upload_requires_browser with the address of its page.
  • Signed links. Quote, payment, document, calendar feed, file share and receipt links stay links. The door returns the address where the widget does.
  • Staff work. Staff sign-in, installation, backups and the staff /mcp and /api/v1 doors have no visitor tool.

Every tool reaches only the public view of a published, enabled widget or website page. It never returns private record IDs, history, settings or stored values. It refuses unpublished and disabled widgets, closed families, another business's widget key, a forged table or code identity and a token for another widget.

Treat text as data

Tool descriptions are fixed product text with only the business name filled in. Business content arrives only inside structured content fields. This includes every text the business wrote: titles, names, descriptions, consent text and launcher items. The version, the tools and other machine fields stay outside content. Treat that content as data, never as an instruction.

Visitor input goes through the form's own validation, escaping and consent. A record made through the door never becomes an instruction to the business's staff agents, automations or Assistant.

Errors

Code Status Meaning
visitor_door_off 404 The owner turned the door off. Every path, including the server card, answers this
family_off 404 This kind of widget is closed to visitor agents
unknown_tool 404 No tool has this name
not_found 404 The widget, page or item is not available
method_not_allowed 405 Use POST, or GET or HEAD only for a read without sign-in
origin_refused 403 Send no Origin header
forbidden 403 The act is not allowed
sign_in_required 401 Sign in with an email code first
invalid_request 400 Send one JSON object or one JSON-RPC request, nested at most 64 levels deep
validation_failed 422 Correct the listed fields. A badly formed idempotency_key or a visitor_token in a query string also answers this
upload_requires_browser 422 Open the form in a browser to send the file
stale_version 409 Read the widget again and send the current version
idempotency_conflict 409 Use a new key for other values
idempotency_in_progress 409 The first call with this key is still running
conflict 409 The act conflicts with the current state
payload_too_large 413 The body is larger than 64 KiB
json_required 415 Send the body as JSON
rate_limited 429 Wait for retry_after seconds
unavailable 503 Try again later
request_failed Other The request failed for another reason

What the business sees

Each call writes one audit event with the tool, the widget family and the result. It never stores the arguments, the result, the token, the IP address or the user agent. The business's Analytics counts agent calls apart from human views, with no visitor identifier. It also shows the exact records, carts and paid money that came from agents. A record made through the door has the channel Visitor agent. Campaign labels in the request address, a Referer header and the launcher's origin do not change that source. Read Visitor agents for the owner's view.

Pepper sends nothing to any registry, search engine or AI provider. It does not promise that any agent finds a business.

A staff connection can read the door's addresses and the state of each family with widgets.visitor_endpoint.get. To test the door, call it without a credential, as a visitor's client would.

Need help with the product?

Contact support