MCP Server masamenu.tr — API & Tool Integration Reference
This document is intended for AI assistants, GPT bots, and automated integrations. It contains precise protocol details, tool schemas, and the authentication flow.
Server information#
| Property | Value |
|---|---|
| Server name | meni-user-data (in the serverInfo of the initialize response) |
| Protocol | MCP 2024-11-05 (Streamable HTTP) |
| Transport | HTTP POST (stateless) |
| Base URL | https://api.masamenu.tr/mcp |
| Content-Type | application/json |
| Format | JSON-RPC 2.0 |
Authentication#
All tool calls require the Authorization header. The address above is an example for masamenu.tr; on another brand, use the URL from your own panel. Bucket names in tools/list schemas are also selected by the request brand.
Option 1: User MCP API key (recommended)#
Authorization: Bearer XXXXXXXXXXXX... (64 hex characters, no prefix)
The key is tied to one user. The bot can see only that user's data.
The
mk_…value shown in the admin panel's key list is the key ID (used inDELETE /api/keys/{keyId}), not the key itself.
Option 2: Cognito JWT token#
Authorization: Bearer eyJraWQi... (JWT id_token)
Obtain it with POST /auth/login. It expires after 1 hour.
Option 3: Admin API key#
Authorization: Bearer <admin_api_key>
Full access to all data. Administrators only.
Obtaining a JWT token#
POST https://api.masamenu.tr/mcp/auth/login
Content-Type: application/json
{
"email": "user@example.com",
"password": "password123"
}
Response:
{
"idToken": "eyJraWQi...",
"accessToken": "eyJraWQi...",
"refreshToken": "eyJjdHki...",
"expiresIn": 3600,
"tokenType": "Bearer"
}
MCP protocol#
Initialization#
POST https://api.masamenu.tr/mcp
Authorization: Bearer <token>
Content-Type: application/json
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": { "name": "my-bot", "version": "1.0" }
}
}
Tool list#
{ "jsonrpc": "2.0", "id": 2, "method": "tools/list", "params": {} }
Calling a tool#
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "имя_инструмента",
"arguments": { ... }
}
}
Success response: result.content[0].text is a JSON string containing the data.
Error response: result.isError: true; result.content[0].text contains the error text.
Endpoints#
| Method | Path | Authorization | Description |
|---|---|---|---|
GET |
/ |
No | Server information + tool list |
POST |
/ |
Yes | MCP JSON-RPC |
GET |
/health |
No | Health check → {"status":"ok"} |
POST |
/auth/login |
No | Login → JWT tokens |
GET |
/api/keys |
JWT or own MCP key | List API keys |
POST |
/api/keys |
JWT or own MCP key | Create an API key |
DELETE |
/api/keys/{keyId} |
JWT or own MCP key | Revoke an API key |
/api/keysis authorized as the user: either a Cognito JWT or that user's own 64-character MCP key works. An admin key does not work because it has no user binding; the response is403 user identity required.
All paths are relative to
https://api.masamenu.tr/mcp.
Complete tool reference#
Access levels#
- USER — Operations on behalf of an authenticated user; order-isolation limitations are described below
- ADMIN — Administrators only (full access)
Self-service#
| Tool | Access | Arguments |
|---|---|---|
whoami |
USER | none |
my_profile |
USER | none |
update_my_profile |
USER | fields (object, required) |
my_locations |
USER | none |
my_orders |
USER | limit (int, optional) |
my_images |
USER | type (enum: all, menu-photos, category-photos, locations, optional) |
User profiles#
| Tool | Access | Arguments |
|---|---|---|
list_users |
ADMIN | limit (int, optional) |
get_user_profile |
USER/ADMIN | userId (string, required) |
update_user_profile |
USER/ADMIN | userId (string, required), fields (object, required) |
search_user_by_email |
ADMIN | email (string, required) |
Locations#
| Tool | Access | Arguments |
|---|---|---|
list_locations |
USER/ADMIN | userId (string, required) |
get_location_profile |
USER/ADMIN | locationId (string, required), userId (string, optional — auto-detected for regular users) |
update_location_profile |
USER/ADMIN | locationId (string, required), fields (object, required), userId (string, optional) |
get_location_menu |
USER/ADMIN | locationId (string, required), language (string, optional), userId (string, optional) |
update_location_profilefields that can be updated: displayName, phone, address, facebookUrl, instagramUrl, status, settings, workingHours. The CDN is synchronized automatically. Useset_location_domainto change the domain.
Menu#
| Tool | Access | Arguments |
|---|---|---|
list_menu_items |
USER/ADMIN | categoryId (string, optional — for full data), userId (string, optional) |
get_menu_item |
USER/ADMIN | itemId (string, required), categoryId (string, optional — auto-search), userId (string, optional) |
update_menu_item |
USER/ADMIN | itemId (string, required), fields (object, required), categoryId (string, optional), userId (string, optional) |
create_menu_item |
USER/ADMIN | locationId, categoryId, itemId, name (string, required), price (number, required), nameTranslations (object, optional), description (string, optional), status (enum, optional), sortOrder (number, optional), userId (string, optional) |
create_menu_category |
USER/ADMIN | locationId, categoryId, name (string, required), nameTranslations (object, optional), status (enum, optional), sortOrder (number, optional), userId (string, optional) |
update_menu_category |
USER/ADMIN | locationId, categoryId (string, required), name (string, optional), nameTranslations (object, optional), status (enum, optional), sortOrder (number, optional), userId (string, optional) |
move_menu_item |
USER/ADMIN | locationId, itemId, fromCategoryId, toCategoryId (string, required), userId (string, optional) |
merge_categories |
USER/ADMIN | locationId, sourceCategoryId, targetCategoryId (string, required), keepSourceName (bool, optional), userId (string, optional) |
delete_menu_category |
USER/ADMIN | locationId, categoryId (string, required), force (bool, optional — delete with items), userId (string, optional) |
check_translations |
USER/ADMIN | locationId (string, required), languages (array, optional — languages to check), userId (string, optional) |
check_translationsscans every category and dish in the location, finds missing translations for enabled languages, and returns a detailed language report listing categories and dishes without translations.
Application languages#
| Tool | Access | Arguments |
|---|---|---|
get_my_languages |
USER | none |
set_my_languages |
USER | languages (string[], required — complete list of enabled language codes) |
reorder_my_languages |
USER | order (string[], required — codes in desired order; unspecified codes go to the end) |
Allowed codes:
ka, en, ru, tr, hy, zh, hi, es, fr, ar, bn, pt, id, ur, de, ja, ko, vi, it, pl, uk, fa, he, az, kk, uz, ab, sq, sr, mk, bg, ro, el, nl, mt, sv, no, da, fi, cs, hu, hr, lt, th, ms.
Working hours#
| Tool | Access | Arguments |
|---|---|---|
set_working_hours |
USER/ADMIN | locationId (required), days (string[], optional), schedule (object, optional — {closed, periods:[{open,close}]}), perDay (object, optional — day→schedule map, overrides days+schedule), userId (optional) |
list_schedule_exceptions |
USER/ADMIN | locationId (required), userId (optional) |
add_schedule_exception |
USER/ADMIN | locationId, date (YYYY-MM-DD), isClosed (bool) — required; timeFrom, timeTo (HH:MM, required when isClosed:false), userId (optional) |
remove_schedule_exception |
USER/ADMIN | locationId (required), date or exceptionId, userId (optional) |
Days not specified in
set_working_hoursremain unchanged. Callingadd_schedule_exceptionagain for the same date replaces the existing exception.
update_menu_itemfields that can be updated: name, description, price, status, tags, variantGroups, addons, nameTranslations, descriptionTranslations, locationPrices, sortOrder. The CDN is synchronized automatically.
Orders#
| Tool | Access | Arguments |
|---|---|---|
list_orders |
USER/ADMIN | userId (optional), domain (optional), limit (int, optional) |
get_order |
USER/ADMIN | orderId (string, required), domain (string, optional), locationId (string, optional) |
Domains#
| Tool | Access | Arguments |
|---|---|---|
check_domain_availability |
USER | domainName (string, required), currentDomainName (string, optional) |
set_location_domain |
USER/ADMIN | locationId (string, required), domainName (string, required) |
resolve_domain |
USER | domain (string, required) |
list_domains |
ADMIN | prefix (string, optional) |
CDN#
| Tool | Access | Arguments |
|---|---|---|
get_cdn_profile |
USER | domain (string, required) |
get_cdn_menu |
USER | domain (string, required), language (string, required) |
list_cdn_files |
USER | domain (string, required) |
invalidate_cdn_cache |
ADMIN | paths (string[], required) |
Images#
| Tool | Access | Arguments |
|---|---|---|
list_user_images |
USER/ADMIN | userId (string, required), type (enum, optional) |
get_image_upload_url |
USER | type (enum: menu-photos, category-photos, locations, required), itemId (string, optional), locationId (string, optional), filename (string, optional), contentType (enum, optional) |
delete_image |
USER/ADMIN | key (string, required — full S3 key in i.masamenu.tr) |
get_image_upload_urlreturns a presigned URL (15 minutes). After upload, the pipeline automatically generates thumbnails and synchronizes them with the CDN.
S3 storage#
| Tool | Access | Arguments |
|---|---|---|
s3_read |
USER/ADMIN | bucket (enum), key (string) — required |
s3_write |
ADMIN | bucket (enum: data.meni, cdn.masamenu.tr, o.masamenu.tr), key (string), data (object) — required |
s3_list |
USER/ADMIN | bucket (enum), prefix (string) — required, limit (int, optional) |
s3_delete |
ADMIN | bucket (enum: data.meni, cdn.masamenu.tr, o.masamenu.tr), key (string) — required |
Bucket enum: data.meni, cdn.masamenu.tr, i.masamenu.tr, o.masamenu.tr.
Cognito#
| Tool | Access | Arguments |
|---|---|---|
cognito_list_users |
ADMIN | filter (string, optional), limit (int, optional) |
cognito_get_user |
ADMIN | username (string, required) |
System#
| Tool | Access | Arguments |
|---|---|---|
get_system_stats |
ADMIN | none |
Access control#
- Profile and self-service tools use the regular user’s own
userId - Low-level access to data and image buckets is restricted to the
users/{userId}/prefix; published CDN data is read by domain - For location/menu tools,
userIdis auto-detected for regular users (only admins provide it) - Admin-only:
list_users,search_user_by_email,list_domains,invalidate_cdn_cache,s3_write,s3_delete,cognito_list_users,cognito_get_user,get_system_stats update_user_profileis also available to regular users: the schema requiresuserId, but for non-admins the server always substitutes their own identifier, so the tool cannot change another user's profile- Key management (
/api/keys) requires user-bound authorization: a Cognito JWT or the user's own MCP key (an admin key is not accepted)
Known access-control limitation: server-side domain ownership checks for reading orders are incomplete. Do not treat the USER role as a complete isolation boundary for untrusted integrations. Connect only trusted applications; see the API reference.
Error codes#
| HTTP | Meaning |
|---|---|
200 |
JSON-RPC response: check error and result.isError, not just the HTTP status |
202 |
JSON-RPC notification without an id accepted |
400 |
Invalid REST request; JSON-RPC errors themselves return HTTP 200 |
401 |
Missing or invalid authentication |
403 |
user identity required — /api/keys called without a user binding (with an admin key) |
404 |
Unknown path |
405 |
Wrong HTTP method |
| Tool error | Meaning |
|---|---|
🔒 admin access required |
Admin role required |
🔒 access denied |
Attempt to access another user's data |
missing required argument: <name> |
Required parameter was not provided |
unknown tool: <name> |
Unknown tool |
Example session#
→ POST / {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"bot","version":"1.0"}}}
← {"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2024-11-05","capabilities":{"tools":{}},"serverInfo":{"name":"meni-user-data","version":"1.0.0"}}}
→ POST / {"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"whoami","arguments":{}}}
← {"jsonrpc":"2.0","id":2,"result":{"content":[{"type":"text","text":"{\"userId\":\"abc-123\",\"email\":\"user@example.com\"}"}]}}
Client configuration#
Claude Desktop#
{
"mcpServers": {
"meni": {
"url": "https://api.masamenu.tr/mcp",
"headers": { "Authorization": "Bearer <API_KEY>" }
}
}
}
cURL#
curl -X POST https://api.masamenu.tr/mcp \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <API_KEY>" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"whoami","arguments":{}}}'