SOPSellers' Open Protocol

Protocols and standards

Which protocols and standards SOP uses, and how far each one goes.

The status differs by item; see the table below.

Which protocol is used at each step on SOP
AgentSOPMCP tools/list, orREST /api/v1Tools and bookingendpointsrequest_bookingpayment_handlers inUCP format(com.stripe.payments)complete_booking witha Shared Payment TokenOr pay the paymentlink with MPP or x402(testnet)/openapi.jsondescribes the paymentlink
Steps
  1. Agent → SOP: MCP tools/list, or REST /api/v1
  2. SOP → Agent: Tools and booking endpoints
  3. Agent → SOP: request_booking
  4. SOP → Agent: payment_handlers in UCP format (com.stripe.payments)
  5. Agent → SOP: complete_booking with a Shared Payment Token
  6. Agent → SOP: Or pay the payment link with MPP or x402 (testnet)
  7. SOP → Agent: /openapi.json describes the payment link

Summary

Protocol or standardPurposeStatus
MCP (Model Context Protocol)Lets agents call toolsLive (Streamable HTTP, 9 tools)
REST APIShares one core with MCPLive
OpenAPI discovery document /openapi.jsonDescribes the payment link (the payable operation)Live (payment information is testnet only)
UCP payment handler (com.stripe.payments)Tells agents which payment handlers can be usedLive (booking responses use this format)
The rest of UCP (checkout, identity linking, orders, and the discovery file /.well-known/ucp)A full cross-platform commerce flowPlanned (not implemented)
MPP and x402Let agents pay directly over HTTP 402Testnet
ACP and AP2Other agentic commerce protocolsPlanned (not implemented)

MCP and REST

Both share one booking core and behave the same way. For the tool list and endpoints, see Connect to bookings.

UCP

The Universal Commerce Protocol (UCP) is an open standard (ucp.dev) that covers checkout, identity linking, order tracking and payment credential exchange. SOP's booking responses describe payment methods in UCP's payment handler format; full UCP checkout and the /.well-known/ucp discovery file (Planned) are not implemented.

MPP and x402

Both are open protocols that let an agent pay directly over HTTP 402. SOP offers them on testnet only for now; see Machine payments.

Discovery document

/openapi.json is currently the only machine-readable discovery document, and it marks payable operations with x-payment-info.

Read the discovery document: /openapi.json

curl

curl -sS "https://mcp.srct.tw/openapi.json" \
  -H "User-Agent: my-agent/1.0"

Python

import json
import urllib.error
import urllib.request

BASE = "https://mcp.srct.tw"


def call(method, path, body=None, headers=None):
    req = urllib.request.Request(
        BASE + path,
        data=None if body is None else json.dumps(body).encode(),
        method=method,
        headers={"User-Agent": "my-agent/1.0", "Content-Type": "application/json", **(headers or {})},
    )
    try:
        with urllib.request.urlopen(req) as res:
            return res.status, json.loads(res.read())
    except urllib.error.HTTPError as err:  # 4xx and 5xx responses still carry a JSON body
        return err.code, json.loads(err.read())


def show(status, body):
    print("HTTP", status)
    print(json.dumps(body, ensure_ascii=False, indent=2))


show(*call("GET", "/openapi.json"))

Node.js

const BASE = "https://mcp.srct.tw";

async function call(method, path, body, headers = {}) {
  const res = await fetch(BASE + path, {
    method,
    headers: { "User-Agent": "my-agent/1.0", "Content-Type": "application/json", ...headers },
    body: body === undefined ? undefined : JSON.stringify(body),
  });
  return { status: res.status, body: await res.json() };
}

function show({ status, body }) {
  console.log("HTTP", status);
  console.log(JSON.stringify(body, null, 2));
}

(async () => {
  show(await call("GET", "/openapi.json"));
})();

Example response

HTTP 200
{
  "openapi": "3.1.0",
  "info": {
    "title": "… booking payments",
    "version": "1.0.0",
    "description": "Pay for … bookings with x402 or MPP. Create the booking first with the MCP tool request_booking or POST /api/v1/businesses/{business_id}/bookings; use the payment_link it returns."
  },
  "servers": [
    {
      "url": "https://mcp.srct.tw"
    }
  ],
  "x-service-info": {
    "categories": [
      "booking",
      "fitness",
      "services"
    ],
    "docs": {
      "homepage": "https://mcp.srct.tw/",
      "apiReference": "https://mcp.srct.tw/docs"
    }
  },
  "paths": {
    "/pay/{business_id}/{booking_id}": {
      "post": {
        "summary": "Pay for a booking (x402 or MPP)",
        "parameters": [
          {
            "name": "business_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "booking_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "t",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "pay token from the booking's payment_link"
          }
        ],
        "x-payment-info": {
          "offers": [
            {
              "intent": "charge",
              "method": "evm",
              "amount": null,
              "currency": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
              "description": "USDC on Base Sepolia (test network); also accepted as x402 exact"
            },
            {
              "intent": "charge",
              "method": "tempo",
              "amount": null,
              "currency": "0x20c0000000000000000000000000000000000000",
              "description": "pathUSD on Tempo test network (Moderato)"
            }
          ]
        },
        "responses": {
          "200": {
            "description": "Paid: booking and payment result"
          },
          "402": {
            "description": "Payment Required: x402 PAYMENT-REQUIRED and MPP WWW-Authenticate challenges"
          },
          "409": {
            "description": "Booking not payable"
          },
          "410": {
            "description": "Payment window passed"
          }
        }
      },
      "get": {
        "summary": "Pay for a booking (x402 or MPP)",
        "parameters": [
          {
            "name": "business_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "booking_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "t",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "pay token from the booking's payment_link"
          }
        ],
        "x-payment-info": {
          "offers": [
            {
              "intent": "charge",
              "method": "evm",
              "amount": null,
              "currency": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
              "description": "USDC on Base Sepolia (test network); also accepted as x402 exact"
            },
            {
              "intent": "charge",
              "method": "tempo",
              "amount": null,
              "currency": "0x20c0000000000000000000000000000000000000",
              "description": "pathUSD on Tempo test network (Moderato)"
            }
          ]
        },
        "responses": {
          "200": {
            "description": "Paid: booking and payment result"
          },
          "402": {
            "description": "Payment Required: x402 PAYMENT-REQUIRED and MPP WWW-Authenticate challenges"
          },
          "409": {
            "description": "Booking not payable"
          },
          "410": {
            "description": "Payment window passed"
          }
        }
      }
    }
  }
}

Run against the live service (read-only)

Payment handler fields

FieldValue
idstripe_payments
typecom.stripe.payments
version2026-06-25
available_instrumentscard, and link with config.network_id
config.environmentlivemode in production, testmode in tests
config.business_profileThe Stripe profile the credential must be issued to

Apple Pay and Google Pay are not offered as instruments.

Security