60% (SIXTY PERCENT) catalog MCP server
Read-only Model Context Protocol server for the public catalog of 60% (SIXTY PERCENT), a Japanese online store for Korean and Asian fashion brands operated by SIXTY PERCENT Inc. (株式会社シックスティーパーセント). Server name sixty-percent-catalog, version 1.0.0.
1. Overview
- Intended users: shoppers in Japan (and anyone researching Korean / Asian fashion) using an AI assistant to find items, compare prices and discover brands sold on 60%.
- Supported tasks: search products by keyword and filters, see new arrivals and sale items, read a product's full details (sizes, colors, stock, price, shipping lead time, reviews), search brands and read a brand's profile and top products, browse the category tree.
- What it improves over the browser: structured results (prices, discounts, stock per variant, lead times) across the whole catalog in one call, with stable product and brand URLs the user can open to view or buy.
- Not included (by design): anything that needs a customer account or changes state — cart, checkout, payment, favorites, followed brands, order status. Purchases happen on the 60% website or app via the returned
url. A future version may add account-bound read tools behind OAuth. - Region, language, currency: the catalog is for Japan. Prices are in JPY including Japanese consumption tax. Shipping is to addresses in Japan only. Names and descriptions are Japanese by default; pass
language: "en"for English where a translation exists. No age restriction applies to the catalog data.
2. Setup
| Transport | MCP Streamable HTTP (protocol version 2025-06-18 and later; the server also accepts 2025-03-26 clients). Stateless: no session id is issued, every POST is independent, responses are plain JSON. |
|---|---|
| Endpoint | https://mcp.sixty-percent.com/mcp (POST only; GET returns 405 because there are no server-initiated messages) |
| Authentication | None. The server returns only public catalog data, so no OAuth, API key or account is required. There are no scopes and no user credentials involved. A test account is therefore not needed to exercise any tool; every tool can be called anonymously. |
| Environment | Production. The data is the live catalog of www.sixty-percent.com (same backend as the website and the 60% apps). |
| Documentation | https://mcp.sixty-percent.com/docs (this page) |
| Health check | GET https://mcp.sixty-percent.com/healthz → 200 ok |
Example: list the tools with curl.
curl -s https://mcp.sixty-percent.com/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"0"}}}'
curl -s https://mcp.sixty-percent.com/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'
curl -s https://mcp.sixty-percent.com/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"search_products","arguments":{"query":"ニット","gender":"women","price_max":8000,"limit":5}}}'
With the MCP Inspector: npx @modelcontextprotocol/inspector, choose transport “Streamable HTTP”, URL https://mcp.sixty-percent.com/mcp, no authentication.
3. Tool classification
All 7 tools are Read in the sense of the Muse connector guidelines (section 3.2): they retrieve information and never create, change or delete data, account state or permissions, and never act on the user's behalf. There are no Write and no Sensitive write tools. No tool sends messages, publishes content, places orders or moves money. Each tool carries the MCP annotations readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false, so clients can run them without per-call approval.
| Tool | Classification | Sensitive | Side effects |
|---|---|---|---|
search_products | Read | No | None |
get_product | Read | No | None |
list_new_arrivals | Read | No | None |
list_sale_products | Read | No | None |
search_brands | Read | No | None |
get_brand | Read | No | None |
list_categories | Read | No | None |
4. Tools
search_products— Keyword search over the whole catalog with filters for section (women/men), category, brand, price range and sale status.get_product— Everything about one product: description, all images, every size/color variant with price and stock level, brand, shop, category, tags, shipping lead time and review summary.list_new_arrivals— Most recently added products, newest first, with the same section / category / brand / price filters.list_sale_products— Discounted products, biggest discount first by default, with an optional minimum discount.search_brands— Find brands by name, or list brands, optionally only those running a sale or from a given country.get_brand— Profile of one brand with its top products.list_categories— The category tree (top-level categories with their sub-categories) and the ids to use as filters.
Every tool returns the result both as structuredContent (JSON object) and as a text content block containing the same JSON, so it works with clients that read either. Money values are objects {amount: number, currency: "JPY", text: "¥2,945"}. Pagination is cursor based: pass the returned next_cursor as cursor to get the next page; null means the last page. All url fields point to www.sixty-percent.com pages that open in the browser or the 60% app.
search_products Read
Keyword search over the whole catalog with filters for section (women/men), category, brand, price range and sale status.
Inputs
| Name | Type and meaning |
|---|---|
query | string ≤ 200 chars, optional. Keywords in Japanese, Korean or English. Omit to browse by filters only. |
gender | "women" | "men", optional. |
secondary_category_id | string, optional. Top-level category id from list_categories. |
tertiary_category_id | string, optional. Sub-category id from list_categories. Overrides secondary_category_id. |
brand_id | string, optional. Brand id from search_brands / get_brand. |
price_min | integer ≥ 0, optional. Minimum price in JPY. |
price_max | integer ≥ 0, optional. Maximum price in JPY. |
on_sale | boolean, optional. true = discounted items only. |
in_stock | boolean, default true. true = purchasable now. |
sort | recommended (default) | newest | price_low_to_high | price_high_to_low | discount_high_to_low | best_selling | most_favorited | review_rating |
limit | integer 1–50, default 20. |
cursor | string, optional. next_cursor from the previous page. |
language | "ja" (default) or "en". Language of names and descriptions. Prices are always JPY. |
Output
total_count (number of matches; the search index caps it at 15,000), count, products[] (id, title, url, brand {id, name, url, country}, category, gender, price {amount, currency, text}, price_max, compare_at_price, discount_percent, on_sale, available_for_sale, coming_soon_at, first_published_at, image_url) and next_cursor (null on the last page).
get_product Read
Everything about one product: description, all images, every size/color variant with price and stock level, brand, shop, category, tags, shipping lead time and review summary.
Inputs
| Name | Type and meaning |
|---|---|
product_id | string. Product id from search results. Provide this or handle. |
handle | string. Last path segment of a product page URL (https://www.sixty-percent.com/products/<handle>). |
language | "ja" (default) or "en". |
Output
id, title, url, brand, shop, category, sub_category, gender, description (plain text), price, price_max, compare_at_price, discount_percent, on_sale, available_for_sale, end_of_sale, sale_type (regular | pre_order | back_order), pre_order_date, coming_soon_at, first_published_at, estimated_delivery_business_days, free_shipping, ships_to (["JP"]), favorite_count, review {average, count}, tags, seasons, images[] {url, color}, size_chart, variants[] {id, title, options, color, price, compare_at_price, available_for_sale, stock (in_stock | low_stock | sold_out)}. Returns an error result (isError) when the product does not exist or is no longer on sale.
list_new_arrivals Read
Most recently added products, newest first, with the same section / category / brand / price filters.
Inputs
| Name | Type and meaning |
|---|---|
gender | "women" | "men", optional. |
secondary_category_id | string, optional. Top-level category id from list_categories. |
tertiary_category_id | string, optional. Sub-category id from list_categories. Overrides secondary_category_id. |
brand_id | string, optional. Brand id from search_brands / get_brand. |
price_min | integer ≥ 0, optional. Minimum price in JPY. |
price_max | integer ≥ 0, optional. Maximum price in JPY. |
limit | integer 1–50, default 20. |
cursor | string, optional. next_cursor from the previous page. |
language | "ja" (default) or "en". Language of names and descriptions. Prices are always JPY. |
Output
total_count (number of matches; the search index caps it at 15,000), count, products[] (id, title, url, brand {id, name, url, country}, category, gender, price {amount, currency, text}, price_max, compare_at_price, discount_percent, on_sale, available_for_sale, coming_soon_at, first_published_at, image_url) and next_cursor (null on the last page).
list_sale_products Read
Discounted products, biggest discount first by default, with an optional minimum discount.
Inputs
| Name | Type and meaning |
|---|---|
min_discount_percent | 50 | 70 | 90, optional. Only items discounted at least this much. |
gender | "women" | "men", optional. |
secondary_category_id | string, optional. Top-level category id from list_categories. |
tertiary_category_id | string, optional. Sub-category id from list_categories. Overrides secondary_category_id. |
brand_id | string, optional. Brand id from search_brands / get_brand. |
price_min | integer ≥ 0, optional. Minimum price in JPY. |
price_max | integer ≥ 0, optional. Maximum price in JPY. |
sort | same values as search_products, default discount_high_to_low. |
limit | integer 1–50, default 20. |
cursor | string, optional. next_cursor from the previous page. |
language | "ja" (default) or "en". Language of names and descriptions. Prices are always JPY. |
Output
total_count (number of matches; the search index caps it at 15,000), count, products[] (id, title, url, brand {id, name, url, country}, category, gender, price {amount, currency, text}, price_max, compare_at_price, discount_percent, on_sale, available_for_sale, coming_soon_at, first_published_at, image_url) and next_cursor (null on the last page).
search_brands Read
Find brands by name, or list brands, optionally only those running a sale or from a given country.
Inputs
| Name | Type and meaning |
|---|---|
query | string ≤ 100 chars, optional. Brand name or part of it. |
on_sale | boolean, optional. true = brands with a sale running now. |
country | ISO 3166-1 alpha-2, optional, e.g. KR. |
limit | integer 1–50, default 20. |
language | "ja" (default) or "en". |
Output
count, brands[] (id, name, name_kana, url, country, logo_url, favorited_count, products_count, current_sale_max_discount_percent, on_sale, has_recent_new_arrivals). Not paginated: raise limit or narrow the query to see more.
get_brand Read
Profile of one brand with its top products.
Inputs
| Name | Type and meaning |
|---|---|
brand_id | string. Brand id. Provide this or handle. |
handle | string. Last path segment of https://www.sixty-percent.com/brands/<handle>. |
products_limit | integer 0–50, default 12. How many top products to include. |
language | "ja" (default) or "en". |
Output
All fields of a search_brands item plus description, instagram_url, cover_image_url, latest_product_published_at, categories[] {id, name} and top_products[] (same shape as search_products items). Error result when the brand does not exist.
list_categories Read
The category tree (top-level categories with their sub-categories) and the ids to use as filters.
Inputs
| Name | Type and meaning |
|---|---|
language | "ja" (default) or "en". |
Output
categories[] {secondary_category_id, name, handle, sub_categories[] {tertiary_category_id, name, handle}}.
5. Status handling and side effects
- There is no server-side state: no sessions, no cursors stored on the server, nothing to retry or roll back. Calling any tool twice with the same arguments returns the same data (modulo catalog updates), so clients may retry freely after a network error or a 5xx/429.
- Reads never modify the catalog, customer data or analytics counters. The server stores no user data and sets no cookies; it logs only operational metadata (request path, status, latency, caller IP for rate limiting) for a short retention period on Cloudflare.
- Stock (
stock,available_for_sale) and prices are live at the time of the call; they are not reserved and may change before the user completes a purchase on the website.
6. Errors
| Situation | Response |
|---|---|
| Invalid arguments (wrong type, out of range) | Tool result with isError: true whose text starts with MCP error -32602: Input validation error and names the offending field; nothing is executed upstream. |
| Product or brand not found | Tool result with isError: true and a human-readable message. |
| Upstream catalog API is rate limiting or unavailable | Tool result with isError: true and a message that says to retry after N seconds. The server never fabricates data. |
| Too many requests from one client | HTTP 429 with Retry-After: 60 and a JSON-RPC error body (see rate limits). |
GET on /mcp, unknown path | HTTP 405 / 404. |
Missing Accept: application/json, text/event-stream or wrong Content-Type | HTTP 406 / 415 per the Streamable HTTP specification. |
7. Rate limits and performance
- 120 requests per minute per client IP on
https://mcp.sixty-percent.com/mcp, counted per Cloudflare location. One tool call is one request (get_brandby id is two upstream calls but one request). Over the limit the server returns HTTP 429 withRetry-After; back off for 60 seconds. - Page size is capped at 50 items. Typical latency is 100–600 ms per call from Japan.
- Requests to the upstream catalog API time out after 15 seconds and are reported as retryable errors.
- If your integration needs a higher limit, contact the support address below with the expected traffic.
8. Data and privacy
- The server processes no personal data from users: tools take only catalog search parameters. It does not accept or forward user identifiers, messages or credentials.
- Returned data is the public catalog (product, price, stock, brand, category and aggregated review scores) already visible on www.sixty-percent.com.
- Privacy policy: https://www.sixty-percent.com/privacy-policy · Terms of use: https://www.sixty-percent.com/terms-of-use
9. Support
- Help center: https://sixtypercent.zendesk.com/hc/ja
- Operator: SIXTY PERCENT Inc., Tokyo, Japan — https://corp.sixty-percent.com/
- Source and change history: the
apps/catalog-mcp-workerdirectory of the operator's monorepo. Deployed on Cloudflare Workers; infrastructure is managed as code.
日本語の要約
このサーバーは 60%(SIXTY PERCENT)の公開カタログ(商品・価格・在庫・ブランド・カテゴリー)を読み取り専用で返す MCP サーバーです。エンドポイントは https://mcp.sixty-percent.com/mcp(Streamable HTTP、認証なし)。ツールは 7 本すべて Read(データ・アカウント・権限を変えず、副作用なし)で、購入・カート・お気に入り・注文状況などログインが要る操作は含みません。価格は日本円(税込)、配送は日本国内のみです。1 クライアント IP あたり 1 分 120 リクエストまで。お問い合わせは ヘルプセンターへ。