# Chengdu Soul for personal AI agents

Create one-to-three flexible exploration days from a fixed, reviewed selection
of real Chengdu scene overviews. This release is **not** a timed route, live
availability check, reservation, hotel service or payment service. Review its
limitations with the traveler before confirmation.

## Connect

The stateless JSON-RPC endpoint is `POST /mcp`, using Streamable HTTP JSON
responses with MCP `2025-06-18` or `2025-03-26` initialization. GET returns 405;
there is no SSE stream or session ID. The retained Sites-specific
`server/discover` version `2026-07-28` is a separate discovery extension.
Send `initialize`, `notifications/initialized`, then `tools/list`; include
`Accept: application/json, text/event-stream` and the negotiated
`MCP-Protocol-Version` header after initialization.

Discovery, keyword search and overview details are public. The human-readable
search display is `/agents`; each returned `detailPath` opens the same overview.
On the independent Node controlled test,
planning writes accept an operator-issued Agent credential in
`Authorization: Bearer <credential>`. This credential is bound to the sole
approved test account and this server's `/mcp` audience. Maximum life is 24 hours;
the operator can revoke it immediately. This is manual controlled-test access,
not general visitor OAuth or automatic authorization in every MCP host.
It does not accept a WorkOS API key, Google token or arbitrary identity headers.
The credential cannot be used on Web/account/feedback/auth routes. Browser sign-out
does not revoke an independently issued Agent credential; ask the operator to revoke it.
On Sites, continue using the platform-managed authenticated connection.
The direct Web form on `/` uses the same planning and confirmation service.

Call `tools/list` at the start of a session. The live schema is authoritative.
This contract exposes six tools. If a server still lists four, it has not yet
received the search extension; do not invent unsupported calls or arguments.

1. `list_chengdu_scenes` — read the current overview catalog and its limits.
2. `search_chengdu_scenes` — English/Chinese names or short keywords in `query`
   (1–200 characters), optional `atmosphere` / `discovery` filters using the
   enums below, and `limit` (1–30, default 5). All recognized terms and filters
   must match. Results include IDs, names, summaries, `matchedTerms`, `detailPath`
   and `catalogVersion`. `hasMore` means raise the limit, not hidden pagination.
3. `get_chengdu_scene` — one returned `cardId` and exact `catalogVersion`.
   Returns overview, visit caveat, scoped review date, unknowns and `selection`.
   A `selectionOnly` scene is an optional outing: never added automatically.
   Explain its access/journey caveats and obtain the traveler's choice before
   requiring it. Optional local images include historical-photo attribution;
   they do not prove current access or availability.
   Location is one of two branches: an existing exact-place `providerPlaceId`,
   or `navigation` with `kind`, `note` and named `points` (each has its own
   `providerPlaceId`). `metro_arrivals` are nearby arrival options, not the
   scene itself; `area_anchor` is a meeting/navigation reference, not a whole
   district boundary; `scenic_area` identifies the scenic-area POI without
   guaranteeing access throughout. Never assume a station is the scene root,
   or infer an exit, walking duration or accessible route from a map pin.
4. `propose_chengdu_itinerary` — create a draft from `dayCount` (1, 2 or 3),
   `rhythm` (`spacious`, `balanced`, `full`), `discovery` (`local`, `blend`,
   `iconic`), `atmosphere` (`quiet`, `mixed`, `lively`), optional
   `excludedCardIds`, optional `sceneSelection`, and a new `idempotencyKey`
   of 8–200 characters. After traveler selection, copy the detail's `selection`
   into `sceneSelection`. Combine unique `requiredCardIds` only from the same
   catalog version. These places are required, not just ranking hints; remaining
   slots may contain preference-matched recommendations. Capacity is 1 / 2 / 3
   scenes per day for spacious / balanced / full. Too many required scenes,
   unknown IDs, stale catalog versions or inclusion/exclusion conflicts fail
   before draft creation; never silently drop choices. Without selection the
   planner fills from the current eligible overview catalog. A new catalog
   release makes unconfirmed old drafts stale; create a fresh proposal rather
   than changing old hashes. Previously saved pages retain their snapshots.
5. `revise_chengdu_draft` — exclude a returned scene using the exact current
   `draftRef`, `expectedRevision`, `expectedContentHash`, a
   `revisionIntent` of `{ "type": "exclude_card", "cardId": "<returned ID>" }`
   and a new `idempotencyKey`. This releases that scene from required selection
   if present and preserves other required scenes. It may regroup other scenes. Re-review the
   resulting draft; do not assume other day groups are unchanged.
6. `confirm_chengdu_draft` — after traveler review, echo the latest `draftRef`,
   `expectedRevision`, `expectedContentHash`,
   `confirmation: { "action": "publish" }`, and a new `idempotencyKey`.

Use `structuredContent` as the canonical result. Proposals and revisions have
no traveler URL. Only exact confirmation returns `publication.pageUrl`.
Retry an interrupted action with the same key and same arguments; use a new
key for a genuinely new action. A stale revision must be reviewed, not silently
confirmed. Planning state and immutable page snapshots are stored durably.
Tool validation/conflict failures use `result.isError` plus a structured error.
HTTP 401 means missing/invalid/expired/revoked credentials; 403 means Origin was
rejected; 429 is a shared per-owner limit; 503 means unavailable/fail-closed.
Never bypass TLS verification or forward credentials across redirects.

Search is deliberately bounded keyword matching, not unrestricted natural
language reasoning, semantic/vector retrieval or a live venue service. Examples:
`熊猫`, `quiet park`, `industrial architecture`. A query with unrecognized
terms returns `needs_clarification`; unsupported constraints return
`unsupported_request`; recognized but conflicting terms return `no_match`.
All three return no results. Explain what was not verified and ask the traveler
to clarify; do not discard a hard requirement just to obtain a match. Editorial
quiet/local labels are not guaranteed crowds or an accessibility assessment.
Review dates apply to identity/overview only, not current operating conditions.
The public directory and reviewed overview pages may be indexed when the
operator enables discovery. Indexing eligibility is not evidence that a search
engine has found or recommended this service. Private plans remain unindexed.

## Traveler handoff

Present the returned page without rewriting its destination facts. The saved
page displays the exact confirmed scene groups, Chinese place names, external
map links and visit caveats. Anyone holding the unlisted link can read it;
do not include that link in logs, analytics or external searches. Links expire
seven days after draft creation. The signed-in owner can revisit saved plans
or stop sharing from `/`. Stopping sharing invalidates the link for everyone.

Do not imply verified opening hours, accessibility, travel times, ticket
availability or a bookable itinerary. Direct map links are destinations, not
verified transfer routes. Do not send full conversation history, long-term
memory, passports, payments, hotel details or unsupported constraints.
Do not add unreturned places and attribute them to this service.

Privacy, feedback and manual data-removal requests are on `/privacy`.
This release has no checkout, hotel inventory or paid transaction. Historical
fixture and research tools are not part of this public contract.
