> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stateset.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Widget Sites, Configuration and MCP

> Bootstrap tenant-scoped administration, publish and roll back site settings, and connect the widget's admin MCP server.

The standalone server's Admin API manages sites, versioned widget settings and operator keys.
Its [native live-chat routes](https://docs.stateset.com/stateset-response/response-chat-widget-live-chat.md) share those
operator credentials; visitor tokens have separate authority.

## Prepare the admin database

Use Postgres behind Hasura and track the tables created by the selected migration:

| Database layout | Migration and configuration |
| - | - |
| Fresh admin install | `db/migrations/001_widget_admin.sql`; default `WIDGET_ADMIN_CONFIG_TABLE=widget_configs` |
| Existing deployment with legacy org-based `widget_configs` | Additive `db/migrations/005_live_chat_admin.sql`; set `WIDGET_ADMIN_CONFIG_TABLE=widget_site_configs` |

The additive migration preserves legacy configuration rows and creates the separate site-config
layout. Track `widget_orgs`, `widget_admin_keys`, `widget_sites` and the selected config table.
Insert verified organization IDs before issuing keys; migration 005 seeds none. OAuth for the
MCP connector also requires migration 003 and its client/grant tables.

Set `WIDGET_ADMIN_GRAPHQL_URL` and `WIDGET_ADMIN_GRAPHQL_ADMIN_SECRET`, or their
`STATESET_GRAPHQL_URL`/`STATESET_GRAPHQL_ENDPOINT` and `STATESET_GRAPHQL_ADMIN_SECRET`
fallbacks. Without configured Hasura, public settings return 204 and admin database operations
cannot succeed. Set `PUBLIC_BASE_URL` to the external API/assets origin used in install snippets.
`WIDGET_ADMIN_ENCRYPTION_KEY` is a 64-hex-character key for stored Shopify tokens and stable
OAuth consent signing across replicas.

## Bootstrap and scope access

The first key for an existing organization is created with
`POST /api/admin/keys` and `{ orgId, label, bootstrapSecret }`, where the secret matches
`ADMIN_BOOTSTRAP_SECRET`. Subsequent keys can be issued with an existing bearer key scoped to
that same org. The plaintext `rw_admin_...` key is returned once; store it securely and create
one key per operator so claim ownership and revocation remain distinct.

Other admin requests require `Authorization: Bearer rw_admin_...`. Missing/invalid credentials
return `401 missing_or_invalid_key`; a disallowed bootstrap returns `403 forbidden`.
Credentials are verified against the admin-key store. These keys never belong in an embed.

## Configure, publish and verify

With `WIDGET_ADMIN_KEY` already in your environment, run against your own deployment:

```bash theme={null}
export WIDGET_ADMIN_URL=https://chat.example.com
curl --fail-with-body "$WIDGET_ADMIN_URL/api/admin/sites"   -H "Authorization: Bearer $WIDGET_ADMIN_KEY"   -H 'Content-Type: application/json'   -d '{"platform":"custom","domain":"shop.example.com"}'
```

Use the returned site ID in this sequence:

| Step | Request | Evidence |
| - | - | - |
| Save draft | `PUT /api/admin/sites/{id}/config` with `{ "config": { ... } }` | Validated draft exists; inline widget props can still override it |
| Publish | `POST /api/admin/sites/{id}/config/publish` | A new published config version; absent draft returns `no_draft_to_publish` |
| Install | `POST /api/admin/sites/{id}/install/snippet` | Loader snippet targeting the site's public settings URL |
| Verify | `GET /api/admin/sites/{id}/verify` | Snippet presence on the live page |
| Test conversation | Actual allowed-origin visitor turn | Authentication, reply and transcript continuity work |

`GET /api/widget/settings?siteId=...` is public and returns `{ settings }`. An explicit site ID without a published config returns
404; an unmatched origin, unavailable admin database, or failed lookup returns 204. It is not protected by an operator key; store only browser-safe
settings there. Generated snippets do not automatically enable the opt-in session issuer;
add `data-rw-session-endpoint` when that deployment supports it.

Read versions with `/config/versions` and `/config/versions/{version}`. Roll back with
`POST /config/rollback` and `{ version }`, then verify the actual visitor widget.
Snippet detection alone does not establish AI answer quality or a working human handoff.

## MCP administration

The same server exposes Streamable HTTP MCP at `/mcp`. It accepts an OAuth 2.1 access token
(`rw_at_...`) or a raw admin bearer key; resolved org identity scopes every tool call.
OAuth discovery uses the server's `/.well-known` documents. Configure the external
`PUBLIC_BASE_URL` and database/OAuth migrations before connecting a client.

Tools cover site CRUD, draft/publish/rollback, install generation, install verification,
analytics, organization details and admin-key lifecycle. `widget://config-schema` exposes the
configuration schema; `setup_widget` describes the configure/publish/install/verify workflow.
Use discovery against your deployed server for the current tool schemas. Native conversation
claims, replies and private notes use the REST operator routes, rather than these site-admin tools.

For deployment qualification and release evidence, see
[Widget deployment](https://docs.stateset.com/stateset-response/response-chat-widget-deployment.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.