Guides
MCP / AI Agent
Connect AI agents via the Streamable-HTTP MCP server and OAuth 2.0.
Use this guide to connect Cursor, Claude Desktop, or mcp-inspector to any Sendy MCP endpoint.
Available endpoints
| URL | Tenant context |
|---|---|
https://<host>/api/v1/store/mcp | Store customer assistant |
https://<host>/api/v1/admin/mcp | Platform admin |
https://<host>/api/v1/delivery-company/mcp | Delivery company |
Transport: Streamable HTTP (MapMcp).
Authentication
MCP endpoints require OAuth 2.0 Bearer tokens — not API keys.
The flow is PKCE authorization code (code_challenge_method=S256). Steps:
-
Start authorization
GET /api/v1/oauth/authorize ?response_type=code &client_id=<registered_client_id> &redirect_uri=<registered_redirect_uri> &code_challenge=<S256_hash_of_verifier> &code_challenge_method=S256 &state=<random> &scope=catalog:read orders:read orders:writeIf the user is not logged in, the server redirects to your login UI with
?request_id=<id>. -
User logs in (if not already authenticated)
POST /api/v1/oauth/login { "requestId": "<id>", "phone": "...", "password": "..." }Accept:
application/jsonto receive{ "data": { "redirectUrl": "..." } }instead of a 302. -
Exchange code for token (form-encoded)
POST /api/v1/oauth/token grant_type=authorization_code &code=<code> &code_verifier=<plain_verifier> &client_id=<client_id> &redirect_uri=<redirect_uri>Response:
{ "access_token": "...", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "...", "scope": "catalog:read orders:read orders:write" } -
Call MCP endpoint
Authorization: Bearer <access_token>
Required scopes per tool
| Tool | Required scope |
|---|---|
get_store_info | catalog:read |
list_categories | catalog:read |
list_provinces | catalog:read |
list_areas | catalog:read |
list_products | catalog:read |
search_products | catalog:read |
get_product | catalog:read |
send_order_otp | orders:write |
create_storefront_order | orders:write |
track_order | orders:read |
Exposed tools
get_store_info— get store name, description, contact details (email, WhatsApp, social links), policies, and FAQslist_categories— list the store's product categories for guided browsinglist_provinces— list provinces the store delivers to, with their codeslist_areas— list delivery areas/districts within a province (param:provinceCode); returns the area ID needed to place an orderlist_products— list all active products in the store catalogsearch_products— full-text search by SKU / name / description (max 50 results)get_product— get one product by UUIDsend_order_otp— send a verification code to the customer's phone via SMS/WhatsApp (param:phone); call beforecreate_storefront_ordercreate_storefront_order— place an order the same way the storefront website does; requires an OTP code (customer name, phone, address, province code, area ID, items)track_order— fetch order detail and status history by public ID (e.g.ORD-20260506-ABC123)
Ordering flow
To place an order the way a customer does on the website:
list_provinces→ customer picks a province (note itscode)list_areaswith thatprovinceCode→ customer picks an area (note itsid)send_order_otpwith the customer'sphone→ a 6-digit code is sent to themcreate_storefront_orderwith the customer details,addressProvinceCode,addressAreaId,items(SKU + quantity), and theotpCodethe customer received
Info endpoint
Each area exposes an info endpoint that returns the MCP server URL, tool names, and required scopes:
GET /api/v1/store/mcp/integration # requires store.oauth_mcp.redirect_uris.view or store_owner
GET /api/v1/admin/mcp/integration # requires admin.oauth_mcp.clients.view
GET /api/v1/delivery-company/mcp/integration # requires dc.tickets.view
Cursor / Claude Desktop config example
{
"mcpServers": {
"sendy-store": {
"url": "https://<host>/api/v1/store/mcp",
"headers": {
"Authorization": "Bearer <oauth_access_token>"
}
}
}
}
Registering redirect URIs
Before the OAuth flow can complete, the redirect_uri must be registered. Stores register their own:
POST /api/v1/store/oauth-mcp/redirect-uris{ "clientId": "...", "redirectUri": "..." }— requiresstore.oauth_mcp.redirect_uris.manage- Admin can manage all clients at
/api/v1/admin/oauth-mcp/clientsand/api/v1/admin/oauth-mcp/redirect-uris
Config keys required on server
OAuthMcp:SigningKey # 32+ byte base-64 — required
OAuthMcp:Issuer
OAuthMcp:Audience
OAuthMcp:AuthorizationCodeLifetimeSeconds (default 60)
OAuthMcp:AccessTokenLifetimeSeconds (default 3600)
OAuthMcp:RefreshTokenLifetimeSeconds (default 86400)
Notes
- API keys do not work on MCP endpoints — only OAuth bearer tokens.
- Tool responses use the same
ApiResponse<T>envelope as REST controllers. - The same tool surface is exposed on all three MCP URLs; context is resolved from JWT claims.
Source: DOCS/03-integrations/store-mcp-server.md