MCP Server
The OlaClick MCP (Model Context Protocol) Server allows AI agents and MCP-compatible clients to interact with the OlaClick Public API. Connect your AI assistant to OlaClick and query orders, clients, and product sales data using natural language.
What is MCP?
Model Context Protocol is an open standard that enables AI assistants (like Claude, Cursor, or any MCP-compatible client) to securely interact with external APIs through a standardized interface. Instead of manually crafting API calls, your AI assistant can use OlaClick tools directly.
Available Tools
The OlaClick MCP server exposes the following tools:
| Tool | Description | Required Scope |
|---|---|---|
get_orders | Retrieve orders with filters (status, service type, source, dates) | orders:read |
get_clients | List clients with filters (name, phone, status, source, points) | clients:read |
get_menu | Menu catalog: categories, products, prices, availability, images | menu:read |
get_products_sold | Product sales statistics (top sellers, quantities, revenue) | orders:read |
update_product | Update a product's name or description | menu:write |
list_categories | List menu categories (id, name, position, type, visibility) | menu:read |
get_category | Get one category by UUID | menu:read |
list_products | Paginated product list, optionally filtered by category | menu:read |
get_product | Get one product by UUID | menu:read |
list_product_variants | List a product's variants (name, price) | menu:read |
list_kitchens | List the company's kitchens | menu:read |
get_company | Company profile: identity, location, business hours, open-now flag | companies:read |
list_payment_methods | Active payment methods of the company | payment-methods:read |
list_users | Paginated company users, filterable by role and account status | users:read |
Quick Start
Prerequisites
- An OlaClick API Key (generated from the restaurant's panel under Integrations > API Keys)
- An MCP-compatible client (Claude Desktop, Cursor, VS Code with Copilot, etc.)
Configuration
The OlaClick MCP server uses HTTP (SSE) transport. Clients connect to the remote endpoint — no local installation needed.
Client Setup
Cursor
Add to CursorOr add manually to your project's .cursor/mcp.json:
{
"mcpServers": {
"olaclick": {
"url": "https://public-api.olaclick.app/mcp",
"headers": {
"Authorization": "Bearer olk_live_YOUR_KEY_HERE"
}
}
}
}
Claude Desktop
Add the following to your Claude Desktop configuration file:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"olaclick": {
"url": "https://public-api.olaclick.app/mcp",
"headers": {
"Authorization": "Bearer olk_live_YOUR_KEY_HERE"
}
}
}
}
VS Code (Copilot / Kiro)
Add the following to .vscode/mcp.json or .kiro/settings/mcp.json:
{
"mcpServers": {
"olaclick": {
"url": "https://public-api.olaclick.app/mcp",
"headers": {
"Authorization": "Bearer olk_live_YOUR_KEY_HERE"
}
}
}
}
Remote HTTP (Hosted)
Connect to the OlaClick MCP server directly via HTTP:
{
"mcpServers": {
"olaclick": {
"url": "https://public-api.olaclick.app/mcp",
"headers": {
"Authorization": "Bearer olk_live_YOUR_KEY_HERE"
}
}
}
}
In HTTP mode, the API key is passed via the
Authorization: Bearerheader on each connection. No environment variables needed.
Tool Reference
Every tool validates its arguments before calling the API: a wrong type, a malformed UUID or a page size out of range is rejected by the MCP server and never reaches OlaClick.
get_orders
Retrieve a paginated list of orders with optional filters.
Note: If no
start_dateis provided, defaults to today's orders.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
order_id | string | No | UUID or public ID (e.g. PE-1234567890) to get a single order |
status | string | No | PENDING, PREPARING, READY, DELIVERED, FINALIZED, CANCELLED |
service_types | string | No | DELIVERY, TAKEAWAY, ONSITE, TABLE (comma-separated) |
source | string | No | Filter by source (e.g. web, ifood, rappi, uber) |
payment_status | string | No | Filter by payment status (e.g. PAID,PENDING) |
payment_method_ids | string | No | Comma-separated payment method UUIDs |
owner_ids | string | No | Comma-separated owner/cashier UUIDs |
rider_ids | string | No | Comma-separated rider UUIDs |
delivered_by | string | No | Filter by who delivered (e.g. MERCHANT,IFOOD,PICKER) |
delivery_status | string | No | Filter by delivery status |
is_scheduled | string | No | Filter scheduled orders (true or false) |
client_id | string | No | Filter by client UUID |
public_id | string | No | Search by partial public order ID |
cancelation_reason | string | No | Filter by cancelation reason |
start_date | string | No | From date (YYYY-MM-DD) |
end_date | string | No | Until date (YYYY-MM-DD) |
start_time | string | No | From time (HH:mm:ss) |
end_time | string | No | Until time (HH:mm:ss) |
time_type | string | No | Date column to filter on (default: pending_at) |
timezone | string | No | Timezone for date filters (default: company timezone) |
page | number | No | Page number (default: 1) |
per_page | number | No | Items per page (1-100, default: 50) |
Example prompt:
"Show me today's pending delivery orders"
Response format:
{
"data": [
{
"id": "9c4f4203-9e2c-403d-88cc-7c0ce9e0f572",
"public_id": "PE-9799906639",
"status": "finalized",
"service_type": "onsite",
"source": "OUTBOUND",
"utm_source": "meta",
"utm_campaign": "combos-julio",
"client": {
"name": "John Doe"
},
"address": {
"city": "Lima",
"area": "Miraflores"
},
"total": 90,
"total_paid": 90,
"total_tips": 0,
"total_discounts": 0,
"delivery_price": 0,
"service_fee_price": 0,
"combos_price": 90,
"created_at": "2026-06-23T18:23:42+00:00",
"updated_at": "2026-06-23T18:56:00+00:00"
}
],
"pagination": {
"current_page": 1,
"per_page": 50,
"total": 12,
"has_more": false
}
}
get_clients
Retrieve a paginated list of clients with optional filters.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
filter_name | string | No | Partial match on client name (accent-insensitive) |
filter_phone_number | string | No | Matches phone number prefix |
filter_country_calling_code | string | No | Country calling code (used with phone_number) |
filter_type | string | No | Frequency classification (comma-separated): ELITE_BUYER, TOP_BUYER, FREQUENT_BUYER, REPEAT_BUYER, BUYER, NO_BUYER |
filter_status | string | No | Recency classification (comma-separated): ACTIVE, INACTIVE, SLEEPING, AT_RISK |
filter_source | string | No | chatbot, ecommerce, panel (comma-separated) |
filter_available_points | number | No | Clients with available_points greater than this value |
filter_used_points | number | No | Clients with used_points greater than this value |
sort_by | string | No | name, phone_number, available_points, used_points, source, total_orders, address |
direction | string | No | asc or desc |
include_addresses | boolean | No | Include client addresses in response |
simple_paginate | boolean | No | Use simple pagination (faster, no total count) |
page | number | No | Page number (default: 1) |
per_page | number | No | Items per page (1-100, default: 25) |
Every client carries two independent classifications, both computed by OlaClick:
type— how often they buy, by lifetime order count:ELITE_BUYER(more than 7 orders),TOP_BUYER(5–7),FREQUENT_BUYER(3–4),REPEAT_BUYER(2),BUYER(1),NO_BUYER(0).status— how recently they bought, by days since their last order:ACTIVE(under 16 days),INACTIVE(16–30),SLEEPING(31–91),AT_RISK(over 91 days, or never ordered).
Combine them to build audiences: filter_status=SLEEPING finds customers about
to churn, while filter_status=AT_RISK plus a type other than NO_BUYER finds
lapsed customers worth winning back.
Example prompt:
"List my top 10 clients sorted by total orders"
Response format:
{
"data": [
{
"id": "9c8e720f-31b1-485a-85fa-0aaf552faaa9",
"name": "John Doe",
"email": "john@example.com",
"phone_number": "3001234567",
"country_calling_code": "57",
"available_points": 150,
"used_points": 0,
"status": "AT_RISK",
"type": "BUYER",
"source": "ecommerce",
"total_orders": 8,
"created_at": "2024-07-19T02:28:48+00:00"
}
],
"pagination": {
"current_page": 1,
"per_page": 25,
"total": 340,
"has_more": true
}
}
get_menu
Retrieve the menu catalog: what you sell, at what price, and whether it's available. This is the source for building product catalogs and ad feeds (Meta / Google Shopping).
Note: the menu is not paginated — a large catalog arrives in a single response. Pass
category_slugto fetch one category at a time.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
category_slug | string | No | Return only this category (e.g. combos) |
available_only | boolean | No | Drop products that are currently unavailable |
Example prompt:
"List my combos with their prices and tell me which ones are out of stock"
Response format:
{
"data": {
"categories": [
{
"id": "026de0fc-85d9-47cd-9c34-627996b6c01c",
"slug": "combos",
"name": "Combos",
"position": 0,
"products": [
{
"id": "9c4f4203-9e2c-403d-88cc-7c0ce9e0f572",
"slug": "combo-classic-smash",
"name": "Combo Classic Smash",
"description": "Smash burger with fries",
"variants": [
{
"id": "6b2f1a04-1c7e-4a2b-9f11-2d8e0b3c4d55",
"name": "Default",
"price": 26,
"currency": "PEN"
}
],
"available": true,
"image_url": "https://assets.olaclick.app/combo-classic-smash.webp"
}
]
}
]
}
}
Prices are in major units (26 means 26.00) with an ISO 4217 currency.
image_url is the primary image only. Products with no variants are omitted,
since they have no price.
get_products_sold
Retrieve statistics about the most sold products.
Note: If no
start_dateis provided, defaults to the last 7 days.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
include | string | No | Grouping: products, products_modifiers, freehand |
show_products | number | No | Limit to top N products |
category_ids | string | No | Comma-separated category IDs |
combo_type | string | No | Freehand combo type filter (only when include=freehand) |
status | string | No | Order statuses (e.g. finalized,delivered) |
sources | string | No | Order sources (e.g. inbound,outbound) |
service_types | string | No | Service types (e.g. delivery,onsite) |
start_date | string | No | Start date (YYYY-MM-DD) |
end_date | string | No | End date (YYYY-MM-DD) |
timezone | string | No | Timezone (default: company timezone) |
page | number | No | Page number (default: 1) |
per_page | number | No | Items per page (1-100, default: 25) |
Example prompt:
"What are my top 5 best-selling products this week?"
Response format:
{
"data": [
{
"product_name": "Combo Classic Smash",
"product_quantity": 41,
"average_price": 39,
"total_sales": 1599,
"modifiers": [],
"product_id": "9c4f4203-9e2c-403d-88cc-7c0ce9e0f572",
"variant_id": "9c4f4203-a0ec-45bc-9810-3a8ada0838dd"
}
],
"pagination": {
"current_page": 1,
"per_page": 25,
"total": 45,
"has_more": true
}
}
update_product
Update a product's name and/or description.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
product_id | string | Yes | UUID of the product to update |
name | string | No** | New product name (max 191 chars) |
description | string | No** | New product description |
**At least one of name or description must be provided.
Example prompt:
"Rename product 9c4f4203-9e2c-403d-88cc-7c0ce9e0f572 to 'Double Smash Burger'"
Response format:
{
"data": {
"id": "9c4f4203-9e2c-403d-88cc-7c0ce9e0f572",
"name": "Double Smash Burger",
"description": "Two smashed beef patties with cheese"
}
}
list_categories
List the company's menu categories: id, name, position, type, visible. No
products, no slug. Use it to browse the catalog structure before listing products.
No parameters. Mirrors GET /v1/menu/categories.
Example prompt:
"Which categories does my menu have, and which ones are hidden?"
get_category
Get a single menu category by UUID.
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string (UUID) | Yes | Category UUID |
Mirrors GET /v1/menu/categories/{id}. A non-UUID id is rejected locally.
list_products
Paginated product list: id, name, description, position, visible,
category_id per product. No variants, no slug.
| Parameter | Type | Required | Description |
|---|---|---|---|
page | integer | No | Page number, 1 or greater (default: 1) |
per_page | integer | No | Items per page, 1-100 (default: 20) |
category_id | string (UUID) | No | Only products in this category |
Mirrors GET /v1/menu/products. A per_page outside 1-100 is rejected locally.
Example prompt:
"List the products in my Combos category"
get_product
Get a single product by UUID: id, name, description, position, visible,
category_id, plus its variants.
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string (UUID) | Yes | Product UUID |
Mirrors GET /v1/menu/products/{id}.
list_product_variants
List the variants of one product: id, name, price, original_price, currency,
sku, stock, stock_threshold, position per variant. Use it to see the purchasable
options of a product returned by get_product or list_products.
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string (UUID) | Yes | Product UUID |
Mirrors GET /v1/menu/products/{id}/variants.
Example prompt:
"What sizes and prices does product 9c4f4203-9e2c-403d-88cc-7c0ce9e0f572 have?"
list_kitchens
List the kitchens configured for the company: id, name, default per kitchen. Use it
to find valid kitchen ids.
No parameters. Mirrors GET /v1/menu/kitchens.
get_company
Get the profile of the company behind the credential: name, description, logo,
public URL, language, currency, location, weekly business hours, and currently_open
computed in the company timezone. Requires the companies:read scope.
No parameters. Mirrors GET /v1/company.
Example prompt:
"Is my restaurant open right now, and what are today's hours?"
list_payment_methods
List the active payment methods of the company: only those enabled for at least one order
service type (ONSITE, TABLE, DELIVERY, TAKEAWAY) are returned. Requires the
payment-methods:read scope.
No parameters. Mirrors GET /v1/company/payment-methods.
list_users
Paginated list of the company's users, with role and account status. Requires the
users:read scope.
| Parameter | Type | Required | Description |
|---|---|---|---|
role | string | No | Comma-separated roles: admin, manager, waiter, rider, cook, sales, cashier |
active | boolean | No | true only active users, false only deactivated users; omit for both |
page | integer | No | Page number, 1 or greater (default: 1) |
per_page | integer | No | Items per page, 1-100 (default: 20) |
Mirrors GET /v1/users, where role and active are sent as filter[role] and filter[active].
Example prompt:
"Which riders do I have active right now?"
Authentication
The MCP server authenticates via the HTTP Authorization header:
Authorization: Bearer olk_live_YOUR_KEY_HERE
The API key is passed on the initial HTTP/SSE connection. All tool calls within that session inherit the key automatically — no need to pass it per-call.
Example Conversations
Here are some example prompts you can use once the MCP server is connected:
| Prompt | Tool Used |
|---|---|
| "How many orders did I get today?" | get_orders |
| "Show me all cancelled orders from last week" | get_orders |
| "List delivery orders that are still pending" | get_orders |
| "Which orders came from my Meta campaigns this month?" | get_orders |
| "Who are my most frequent customers?" | get_clients |
| "Find the client with phone number 300..." | get_clients |
| "Which customers are about to churn?" | get_clients |
| "List my menu with prices" | get_menu |
| "Which products are out of stock right now?" | get_menu |
| "What's my best-selling product this month?" | get_products_sold |
| "Show top 10 products for delivery orders" | get_products_sold |
| "Update the description of product X" | update_product |
| "Which categories does my menu have, and which are hidden?" | list_categories |
| "Show me the products in my Combos category" | list_categories, then list_products |
| "What are the details of product X?" | get_product |
| "What sizes and prices does product X come in?" | list_product_variants |
| "Which kitchens do I have set up?" | list_kitchens |
| "Is my restaurant open right now? What are today's hours?" | get_company |
| "Which payment methods do I accept for delivery?" | list_payment_methods |
| "Which riders are active right now?" | list_users |
| "List my managers and cashiers" | list_users |
Security
- API keys are never logged or stored by the MCP server
- All communication uses HTTPS
- Each user provides their own key via the Authorization header
- Scopes are enforced by the Public API, not by the MCP server: calling a tool
with a key that lacks its scope (e.g.
menu:readforget_menu) fails upstream with403 insufficient_scope
Next Steps
- Getting Started — Get your API key and make your first call
- API Reference — Full endpoint documentation
- Webhooks — Real-time event notifications