# UCP MCP Protocol

This file is published to <a href="https://mcp.g3nretailstack.com/ucp/PROTOCOL.md" target="_blank" rel="noopener noreferrer">https://mcp.g3nretailstack.com/ucp/PROTOCOL.md</a>.

## Usage patterns (headless)
- Stack-wide SOPs & operations catalog: <a href="https://doc.g3nretailstack.com/story/operations.html" target="_blank" rel="noopener noreferrer">/story/operations.html</a>.
- Super-usecase scenarios + QA status: <a href="https://doc.g3nretailstack.com/story/super-usecases.html" target="_blank" rel="noopener noreferrer">/story/super-usecases.html</a>.
- This protocol stays contract-only; use the catalogs for workflow expectations.

## Base URL
- API Gateway: `https://api.g3nretailstack.com/ucp`
- Health check: `GET /ucp/stat` — requires `requireSession` (any authenticated user).

## Auth + tenancy
- **Admin operations:** header auth is canonical (x-session-guid or x-api-key via USM/UAS/OFM).
- **Platform operations:** dual-auth via client_id + client_secret (platform credentials stored in DynamoDB).
- **Bearer token operations:** `Authorization: Bearer <token>` header (OAuth 2.0 access token from identity linking).
- Every admin tenant call requires `x-orgcode`.
- Non-associated callers receive `404 not-found` (anti-enumeration).
- Optional cost attribution: provide `x-cccode` (or request field `cccode`).
- `session_guid` is never emitted in responses; use `stats.session_fingerprint` for correlation.

## Roles
- Admin read: `ucp_admin`, `owner`.
- Admin write: `ucp_admin`, `owner`.
- Platform: client_id + client_secret (no role-based access — scoped by platform_guid).
- Bearer: `Authorization: Bearer <token>` (OAuth 2.0 access token — scoped by customer_guid + scopes).

## Surfaces
- Contract-only surface. Implemented and deployed; see `/ucp/openapi.yaml` for the current surface definition.

## Endpoint inventory (OpenAPI parity)
The endpoints below are implemented and defined in `/ucp/openapi.yaml`. Request/response schema names reference OpenAPI component schemas.

| Method | Path | Auth | Description |
| --- | --- | --- | --- |
| GET | /stat | None/Session | Health/build |
| GET | /.well-known/ucp | None | UCP capability profile per org |
| POST | /checkout/create | Platform | Create checkout session with cart |
| POST | /checkout/get | Platform | Get checkout session state |
| POST | /checkout/update | Platform | Full cart replacement |
| POST | /checkout/complete | Platform | Finalize → SCM order |
| POST | /checkout/cancel | Platform | Cancel checkout session |
| POST | /platform/register | Admin | Register platform credentials |
| POST | /platform/get | Admin | Get platform details |
| POST | /platform/list | Admin | List org platforms |
| POST | /platform/rotate | Admin | Rotate client secret |
| POST | /platform/revoke | Admin | Revoke platform |
| POST | /config/set | Admin | Set UCP org config |
| POST | /config/get | Admin/Platform | Get UCP org config |
| POST | /webhook/config/set | Admin | Set webhook event filters per platform |
| POST | /webhook/config/get | Admin | Get webhook config |
| POST | /webhook/test | Admin | Send test webhook to platform callback_url |
| GET | /identity/.well-known/oauth-authorization-server | None | RFC 8414 OAuth metadata |
| POST | /identity/authorize | Admin | Generate auth code for customer↔platform link |
| POST | /identity/token | Platform | Exchange auth code for access + refresh tokens |
| POST | /identity/revoke | Platform | Revoke token (RFC 7009) |
| POST | /identity/userinfo | Bearer | Get linked customer info |
| POST | /identity/link/list | Admin | List identity links |
| POST | /identity/link/revoke | Admin | Revoke identity link |

## Error tags
Common tags (see [/common/error-tags.html](https://doc.g3nretailstack.com/common/error-tags.html) for definitions): `validation-error`, `unauthorized`, `forbidden`, `not-found`, `conflict`, `invalid-state`, `invalid-fsm-transition`, `throttled`, `internal-error`, `dependency-unavailable`.

## Checkout session FSM
```
incomplete → requires_escalation → ready_for_complete → complete_in_progress → completed
     │              │                      │
     └── canceled ←─┘──────────────────────┘
```

## Example envelopes
Success envelope (shape-only):
```json
{
  "success": true,
  "data": { "session_id": "abc123", "status": "ready_for_complete" },
  "stats": { "service": "ucp", "call": "ucp_checkout_create", "timestamp_utc": "2026-01-01T00:00:00Z", "build": { "build_major": "MONDAY", "build_minor": "0000000000", "build_id": "MONDAY-0000000000" } }
}
```

Error envelope (shape-only):
```json
{
  "success": false,
  "error": {
    "error_code": "ucp.validation_failed",
    "http_status": 400,
    "retryable": false,
    "major": { "tag": "validation-error", "message": { "en_US": "Invalid request." } }
  },
  "stats": { "service": "ucp", "call": "ucp_checkout_create", "timestamp_utc": "2026-01-01T00:00:00Z", "build": { "build_major": "MONDAY", "build_minor": "0000000000", "build_id": "MONDAY-0000000000" } }
}
```

## Idempotency & retries
- All **GET / list** calls are safe to retry with identical inputs (read-only, no side effects).
- **checkout/create** accepts optional `idempotency_key`; duplicate creates return the cached session.
- **checkout/complete** is idempotent on already-completed sessions (returns scm_order_guid).
- **checkout/cancel** is idempotent on already-canceled sessions.

## Webhook delivery (Phase 2)
- **Protocol:** HMAC-SHA256 signed HTTP POST to platform `callback_url`.
- **Signing:** `HMAC-SHA256(signing_secret, "{timestamp}.{json_payload}")`.
- **Headers:** `x-ucp-event-type`, `x-ucp-event-id`, `x-ucp-signature`, `x-ucp-signature-alg: hmac-sha256`, `x-ucp-timestamp`.
- **Timeout:** 6 seconds per delivery attempt.
- **Retry:** Exponential backoff (30s base, 900s max, 5 attempts). Failed deliveries enqueued to sharded GSI4 retry queue. Retry Lambda runs every 2 minutes.
- **Auto-pause:** After 10 consecutive failures, platform `webhook_status` automatically set to `paused`. Re-activate via `POST /webhook/config/set { webhook_status: "active" }`.
- **20 event types:** `order.created`, `order.placed`, `order.fulfilled`, `order.cancelled`, `order.closed`, `order.line_cancelled`, `fulfillment.shipment_created`, `fulfillment.shipment_updated`, `fulfillment.shipment_cancelled`, `fulfillment.delivered`, `return.requested`, `return.authorized`, `return.received`, `return.inspected`, `return.resolved`, `adjustment.refund`, `promise.quoted`, `promise.reserved`, `promise.allocated`, `promise.committed`.
- **Source:** SCM EventBridge bus (`scm-events`), filtered for `channel_code === 'ucp'`.

## Identity Linking (Phase 3)
- **Protocol:** OAuth 2.0 Authorization Code Grant with PKCE support (RFC 6749, RFC 7636, RFC 8414, RFC 7009).
- **Flow:** Admin-mediated — merchant admin calls `/identity/authorize` with `{platform_guid, customer_guid}` to issue a 10-minute auth code. Platform exchanges code for opaque tokens via `/identity/token`.
- **Tokens:** Opaque (not JWT). Access token: 1h TTL. Refresh token: 30d TTL. SHA-256 hashed for DDB lookup.
- **Scopes:** `ucp:checkout_session`, `ucp:order_read`, `ucp:customer_read`.
- **Discovery:** `GET /identity/.well-known/oauth-authorization-server?orgcode=X` returns RFC 8414 metadata.
- **Revocation:** `POST /identity/revoke` (platform, RFC 7009) or `POST /identity/link/revoke` (admin, cascades).

## Configurable Kits
Checkout line items support configurable kits via optional fields on each `line_items[]` entry:
- `variant_id` (string) — PVM variant GUID. **Required** for configurable kit lines (SCM explosion queries PVM by this ID). For standard lines, falls back to `variant_code` or `sku`.
- `uom` (string) — Unit of measure (defaults to `EA` if omitted).
- `kit_type` (`standard` | `configurable`) — Kit type. Must match the variant's `kit_type` in PVM.
- `kit_configuration` (object) — Slot→choices map for configurable kits. Structure: `{ "<slot_code>": [{ "variant_id": "<choice_variant_id>", "qty": <number> }] }`. Nested configurable kits use recursive `kit_configuration` on choice entries.

On `checkout/complete`, UCP maps line items to SCM order lines and forwards all kit fields. SCM validates the configuration against PVM slot/choice/constraint definitions and explodes the kit into component lines for inventory (ICS).

## Stubs (Future)
- **Payment handlers:** Empty array in profile; payment_status always 'none'.


## Known pitfalls
- **Missing `expected_revision`**: most state-changing operations require it; omitting it returns `428` with the current revision in `error.details`.
- **Stale revision**: reading a record, waiting, then writing with an outdated `revision` triggers `409`. Always use the latest revision from the most recent read.
- **Pagination cursors**: `next_token` is opaque JSON. Do not modify, decode, or persist cursors across sessions — they may change format between deploys.
- **Anti-enumeration 404**: some org-scoped reads return `404` even when the record exists, if the caller is not associated with the org. Treat `404` as ambiguous; verify caller association before assuming "not found".

## OpenAPI
- Contract schema: <a href="https://doc.g3nretailstack.com/ucp/openapi.yaml" target="_blank" rel="noopener noreferrer">https://doc.g3nretailstack.com/ucp/openapi.yaml</a>


_Build MONDAY-1776194870 • 2026-04-14T19:27:50.000Z • [© 1999 Microhouse Systems Inc. All rights reserved.](https://doc.g3nretailstack.com/common/copyright-license.html)_
