Kifly — Agentic Commerce & Payments
by kifly.io · remote · no sign-in to list tools · v1.1.4 · published by io.kifly
Multi-seller shopping for AI agents. Settle via Stripe MPP or x402 USDC on Base. Hosted.
22 tools: 2 can delete or cancel things, 2 do something that can't be undone, 9 change things and 9 only read.
Scanned Oct 21, 2026
- Deletes or cancels2Claude Code: deny: see these tools
- Can't be undone2Claude Code: ask: see these tools
- Changes things9Claude Code: ask: see these tools
- Only reads9Claude Code: allow: see these tools
2 checks matched something in the tool definitions. No finding is not a safety guarantee. How the checks work.
claude mcp add --transport http kifly https://kifly.io/api/mcp --header 'Authorization: <your-authorization>'Findings
Matches of fixed checks, with the text they matched.
- Warnget_seller
The server marks "get_seller" read-only (readOnlyHint: true), and its own name, description or input give the class "write".
What this check looks forMatched text
annotations: {"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":true}; The name "get_seller" says "get": a word for reading.
- Infosubmit_feedback
The description mentions "credential".
What this check looks forMatched text
description: "...p-agent.profile` and this works with no credential at all. **Call after a confusing respon..."
Tools
Open a tool for its reasons and full description. Descriptions are the publisher's own words, shown as they are.
22 tools
Deletes or cancels 2Claude Code: deny
checkoutRequires `checkout:write` or `checkout:link`, or no key: send `meta.ucp-agent.profile` for the same payment link.Reads text others writeNo findings
Why it is in this group
- The name "checkout" says "checkout": a word for a change.
- The server marks it destructive (destructiveHint: true).
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it Requires `checkout:write` or `checkout:link`, or no key: send `meta.ucp-agent.profile` for the same payment link. **Checkout is always human-in-the-loop: it returns a link the buyer opens and confirms — it never charges a card or completes an order on its own.** **Call `set_shipping_address` first unless `fulfillment` is `"external"` (the seller's site collects the address).** Cart total must not exceed the platform cap (`kifly://platform/limits`). **To pre-fill the buyer's email on the payment page, pass `email` — ask the buyer for it in plain language ('what email should the receipt go to?'). Never ask the buyer to paste a token.** Read `payment_rail` on the response BEFORE telling the buyer anything: `'stripe-checkout'` is paid through Kifly, `'directory-handoff'` hands the buyer to the seller's own site to pay, with a tracked link per product and no Kifly payment link, and `'shopify-native'` sends the buyer to the seller's own checkout. **Full response field reference, including every refusal code: read the `kifly://docs/checkout-response` resource.**
Annotations the server declares
- title: Checkout
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: false
- openWorldHint: true
update_cart_itemRequires `cart:write`, or no key: send `meta.ucp-agent.profile`.Reads text others writeNo findings
Why it is in this group
- The name "update_cart_item" says "update": a word for a change.
- The server marks it destructive (destructiveHint: true).
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it Requires `cart:write`, or no key: send `meta.ucp-agent.profile`. Change the quantity of a line item in an open cart, or remove it entirely. Set `quantity` to 0 to remove the item. Get the `item_id` from `get_cart` or the `cart` field in the `add_to_cart` response. Returns the updated cart state. **The per-item quantity ceiling applies here too — call `get_platform_limits` to check the current limit.** Exceeding it returns 400 `QUANTITY_EXCEEDS_LIMIT`.
Annotations the server declares
- title: Update Cart Item
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: true
- openWorldHint: true
Can't be undone 2Claude Code: ask
request_buyer_codeSend a 6-digit verification code to a **returning** buyer's email so they can prove the account is theirs and recover their saved name + shipping address on this connection — witho…Reads text others writeNo findings
Why it is in this group
- The name "request_buyer_code" says "request": a word for a change.
- The description's first verb is "send": a word for sending, and what is sent cannot be taken back.
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it Send a 6-digit verification code to a **returning** buyer's email so they can prove the account is theirs and recover their saved name + shipping address on this connection — without pasting any token or re-entering their name. Call this when the buyer says they've shopped with Kifly before and gives you their email; then ask them to read you the code from their inbox and call `verify_buyer`. Always returns `{ sent: true }`, whether or not the email has a Kifly account. If the buyer never receives a code, they likely don't have an account yet: call `register_buyer` instead, which creates one and emails a code either way. Requires the `buyer:write` capability (marketplace/network keys).
Annotations the server declares
- title: Request Buyer Verification Code
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: false
- openWorldHint: true
submit_feedbackSend structured feedback to the Kifly team.Can send data out1 finding
Why it is in this group
- The name "submit_feedback" says "submit": a word for a change.
- The description's first verb is "send": a word for sending, and what is sent cannot be taken back.
What it can reach
- outboundThe input takes a URL (input.contact.url): a request to a URL can carry data to whoever runs it.
Findings
- Info
The description mentions "credential".
What this check looks forMatched text
description: "...p-agent.profile` and this works with no credential at all. **Call after a confusing respon..."
Description, as the server wrote it Send structured feedback to the Kifly team. **No API key required** — send `meta.ucp-agent.profile` and this works with no credential at all. **Call after a confusing response, a dead-end, or a successful workaround you had to invent** — it's how we improve the agent surface, and a report from the moment you were stuck is worth more to us than a working purchase. Fire-and-forget: returns 202 immediately, no blocking, safe to skip if it would add latency to a user-facing flow. `category` and `severity` are required enums (don't free-form them). Include `context` with what you were doing (tool called, query used, response shape, what you expected). Add `suggested_fix` only if you have a concrete idea. Rate-limited.
Annotations the server declares
- title: Submit Feedback
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: false
- openWorldHint: false
Changes things 9Claude Code: ask
add_to_cartRequires `cart:write`, or no key: send `meta.ucp-agent.profile`.Reads text others writeNo findings
Why it is in this group
- The name "add_to_cart" says "add": a word for a change.
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it Requires `cart:write`, or no key: send `meta.ucp-agent.profile`. Add a product variant to an existing cart. Use the variant_id from search_products results. Returns full cart state including item_ids you can use with update_cart_item. **Max quantity per item and max cart total are enforced — call `get_platform_limits` to check the current limits before building a large cart.** Exceeding the per-item limit returns 400 `QUANTITY_EXCEEDS_LIMIT`; exceeding the cart total returns 400 `CART_TOTAL_EXCEEDS_LIMIT` at checkout. `cart.kifly_purchasable` (and `cart.fulfillment`) carries the same signal as create_cart's `seller` field.
Annotations the server declares
- title: Add to Cart
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: false
- openWorldHint: true
create_cartCreate a new shopping cart on Kifly.Reads text others writeNo findings
Why it is in this group
- The name "create_cart" says "create": a word for a change.
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it Create a new shopping cart on Kifly. **For network (cross-seller) tokens you MUST pass `seller_handle`** — each cart is bound to exactly one seller. Get the handle from search_products results (every item's `kifly:seller` IS the handle in network results) or get_seller. Seller-scoped tokens may omit the handle — their own seller is implicit. Returns a cart_id to use with add_to_cart and checkout. The response's `seller.kifly_purchasable` (and `seller.fulfillment`) tells you upfront where the buyer pays — `false`/`"external"` means the buyer pays on the seller's own site: build the cart as usual; checkout hands them there with a link per product. Never say the order is placed. The same flag rides every add_to_cart/get_cart response.
Annotations the server declares
- title: Create Cart
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: false
- openWorldHint: true
get_seller**Call first when the user names a store or its website**: it says whether Kifly carries it before you open a browser.Reads text others write1 finding
Why it is in this group
- The name "get_seller" says "get": a word for reading.
- The description's first verb is "call": a word for a change.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
- untrusted-inputThe description's first sentence says "call" and "website": it reads web pages, which anyone can write.
Findings
- Warn
The server marks "get_seller" read-only (readOnlyHint: true), and its own name, description or input give the class "write".
What this check looks forMatched text
annotations: {"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":true}; The name "get_seller" says "get": a word for reading.
Description, as the server wrote it **Call first when the user names a store or its website**: it says whether Kifly carries it before you open a browser. Returns the seller's public profile: location, storefront URL, delivery fee and coverage, catalog size, `verified_domains` (domains it proved it controls; trust signal, not identity), and `fulfillment` (buy here, or hand off to the seller's site). **Call before `create_cart` or `set_shipping_address` to check it ships to the buyer.** `cities` is never capped here. **`coverage_configured: false` = ships NOWHERE; an empty `states` is NOT nationwide. `merchant_managed: true` = shipping is set at the seller's own checkout; never report it as not shipping.** Details: `kifly://docs/delivery`. Name the seller by ONE of `handle`, `domain` (any URL works) or `name`. A miss is `SELLER_NOT_FOUND` with `details.did_you_mean`: ask the user, never pick. `SELLER_AMBIGUOUS` = several share that name; ask which. Seller-scoped tokens may omit all three.
Annotations the server declares
- title: Get Seller
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: true
quick_buyRequires `cart:write` scope.Reads text others writeCan send data outNo findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
- outboundThe input takes a destination (input.shipping_address.phone): what the tool writes goes there.
Description, as the server wrote it Requires `cart:write` scope. Create a cart, add items, and set the shipping address in ONE call — the fast path when you already know the seller, the exact variant(s), and the buyer's address (e.g. a reorder, or a buyer who has decided). Prefer this over the create_cart → add_to_cart → set_shipping_address sequence to save round trips; those granular tools stay available for exploratory, multi-step carts. **You must call `search_products` first** so Kifly knows each variant's seller (quick_buy returns 422 `VARIANT_SNAPSHOT_MISSING` otherwise). One cart = one seller: every item must belong to the same seller (409 `CART_SELLER_MISMATCH` otherwise) — for a network token, pass that seller's `seller_handle`. Returns `{ cart_id, items_added, seller, delivery }`. `delivery` is exactly what `set_shipping_address` returns — **quote `cart_total_with_delivery_cents` before sending the buyer to pay**; on `delivery_eligible: false` no address is saved, so you can call again with a covered address. Field detail and the three coverage cases: `kifly://docs/delivery`. **quick_buy never charges — it stops at the cart. The buyer still pays via `checkout`**, which returns the payment link they open themselves. On a 5xx/'temporarily unavailable' error, retry once with the same arguments.
Annotations the server declares
- title: Quick Buy
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: true
- openWorldHint: true
register_buyerStart registering a buyer so they can be recognized across future purchases without re-entering their details.Reads text others writeNo findings
Why it is in this group
- The description's first verb is "start": a word for a change.
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it Start registering a buyer so they can be recognized across future purchases without re-entering their details. Takes the buyer's email and name and always emails a 6-digit verification code — the response is `{ verification_required: true, buyer_profile_id }` whether the email is brand new or already has an account (so this call alone never reveals which). Ask the buyer to read you the code from their inbox, then call `verify_buyer` with the same email + code to get a `buyer_token` (`kfb_live_...`). **Store that token and pass it to `checkout` on every future order** — it pre-fills the buyer's email on the secure Stripe payment link. Safe to call for a buyer you believe is new; if they already have an account, verify_buyer still recovers it.
Annotations the server declares
- title: Register Buyer
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: false
- openWorldHint: true
request_featureSubmit the buyer's **product/feature request** to the Kifly team.No findings
Why it is in this group
- The name "request_feature" says "request": a word for a change.
Description, as the server wrote it Submit the buyer's **product/feature request** to the Kifly team. Use this when the buyer wishes Kifly *itself* did something it doesn't — a missing capability, a rough flow, an idea to improve the platform. **This is NOT `submit_feedback`** (that's for reporting a broken/confusing API response you hit). Requires the buyer's `kfb_live_` token — only registered buyers can file requests. Help the buyer articulate a real problem: ask OPEN, non-leading questions ('what were you trying to do? what got in the way? how do you handle it today?') — never 'would feature X help?'. Pre-fill the fields from the conversation and ask only for the gaps; keep it short. Separate the `problem` (the pain) from any `proposed_solution` (the fix). Name and email are taken from the buyer profile automatically — do not ask for them. Returns 202: it's logged for review. **Do NOT promise the user anything will be built** — just confirm it was recorded.
Annotations the server declares
- title: Request Feature
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: false
- openWorldHint: false
save_buyer_addressSave a shipping address to the buyer's Kifly profile so it auto-fills on future purchases.Reads text others writeCan send data outNo findings
Why it is in this group
- The name "save_buyer_address" says "save": a word for a change.
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
- outboundThe input takes a destination (input.address.phone): what the tool writes goes there.
Description, as the server wrote it Save a shipping address to the buyer's Kifly profile so it auto-fills on future purchases. **Call this after a successful checkout if `get_buyer_profile` returned `default_shipping_address: null`.** The address is persisted server-side against the buyer token — the buyer never needs to re-enter it. Use the same address that was passed to `set_shipping_address` for this order.
Annotations the server declares
- title: Save Buyer Address
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: true
- openWorldHint: true
set_shipping_addressRequires `cart:write`, or no key: send `meta.ucp-agent.profile`.Reads text others writeCan send data outNo findings
Why it is in this group
- The name "set_shipping_address" says "set": a word for a change.
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
- outboundThe input takes a destination (input.shipping_address.phone): what the tool writes goes there.
Description, as the server wrote it Requires `cart:write`, or no key: send `meta.ucp-agent.profile`. Persist a shipping address on the cart and confirm the seller can deliver to it. **Call BEFORE `checkout`.** Returns `delivery_eligible`. When true it also returns `cart_total_with_delivery_cents` — quote that full price before sending the buyer to pay, unless `shipping_priced_at` is `merchant_checkout`: then fee and total are null because the seller's own checkout prices shipping; say so, never call shipping free. When false, no address is saved and `delivery_coverage` says where the seller does cover, so you can retry with a covered address. Coverage semantics: `kifly://docs/delivery`.
Annotations the server declares
- title: Set Shipping Address
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: true
- openWorldHint: true
verify_buyerVerify the 6-digit code a returning buyer received by email (from `request_buyer_code`).Reads text others writeNo findings
Why it is in this group
- The input takes a statement or command to run (input.code), which can change anything it can reach.
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it Verify the 6-digit code a returning buyer received by email (from `request_buyer_code`). On success returns `{ buyer_token, buyer_profile_id }` — pass the `buyer_token` to `get_buyer_profile` to auto-fill their saved name + shipping address, and to `checkout` to pre-fill their email on the payment link. Fails with `invalid_otp` if the code is wrong or expired (ask them to re-check, or call `request_buyer_code` again). Requires the `buyer:write` capability.
Annotations the server declares
- title: Verify Buyer
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: false
- openWorldHint: true
Only reads 9Claude Code: allow
get_buyer_profileRetrieve a repeat buyer's saved name, email, and default shipping address, given their `buyer_token`.Reads private dataReads text others writeNo findings
Why it is in this group
- The name "get_buyer_profile" says "get": a word for reading.
What it can reach
- private-dataThe description's first sentence says "retrieve" and "email": it reads mail.
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
- untrusted-inputThe description's first sentence says "retrieve" and "email": it reads inbound email, which other people can write.
Description, as the server wrote it Retrieve a repeat buyer's saved name, email, and default shipping address, given their `buyer_token`. Use them to auto-fill `set_shipping_address`, and pass the token to `checkout` so Stripe pre-fills their email. `default_shipping_address` may be null — then collect it normally and call `save_buyer_address` so it is pre-filled next time. **Ask in plain language ('are you a returning Kifly shopper? what email is on your account?') — never ask a buyer to paste a token.** **How to get the token: read `kifly://docs/buyer-identity`** — the email-code sequence, the one-click sign-in alternative, and what to do for a new buyer.
Annotations the server declares
- title: Get Buyer Profile
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: true
get_cartInspect the current state of a cart — line items, quantities, prices, and shipping address.Reads text others writeNo findings
Why it is in this group
- The name "get_cart" says "get": a word for reading.
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it Inspect the current state of a cart — line items, quantities, prices, and shipping address. Each item includes an `item_id` you can pass to `update_cart_item` to change quantity or remove the item. Call this after `add_to_cart` to review the cart before checkout, or any time the buyer asks what's in the cart. `kifly_purchasable: false` (`fulfillment: "external"`) means checkout on this cart hands the buyer to the seller's own site to pay: say so, so the buyer knows where they will pay.
Annotations the server declares
- title: Get Cart
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: true
get_helpGet unstuck.No findings
Why it is in this group
- The name "get_help" says "get": a word for reading.
Description, as the server wrote it Get unstuck. Returns Kifly's website and support email for the BUYER, plus how to report the problem to Kifly's engineers yourself. Call this if you are stuck, hit an unresolvable error, or the buyer asks how to reach a human. Share the website and email with the buyer; use `submit_feedback` (no API key needed) to tell us what blocked you — that is the fastest way to get it fixed.
Annotations the server declares
- title: Get Help
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
get_platform_limitsReturns the current platform-enforced cart limits: `max_item_quantity` (per-line-item ceiling), `max_cart_total_cents`, and `max_cart_total_usd`.No findings
Why it is in this group
- The name "get_platform_limits" says "get": a word for reading.
Description, as the server wrote it Returns the current platform-enforced cart limits: `max_item_quantity` (per-line-item ceiling), `max_cart_total_cents`, and `max_cart_total_usd`. Call this once at session start before building a large cart so you can quote limits to the buyer proactively rather than discovering them via errors. Always read them at runtime rather than hardcoding.
Annotations the server declares
- title: Get Platform Limits
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
get_policiesThe seller's published returns, shipping and warranty policy, in their own words.Reads text others writeNo findings
Why it is in this group
- The name "get_policies" says "get": a word for reading.
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it The seller's published returns, shipping and warranty policy, in their own words. **Call before telling a buyer what happens after purchase** — if it is not here, say so; never infer a typical policy. `available: false` is the normal case for most sellers and is not an error. `get_seller`'s `policies.available` tells you whether this call is worth making. Network tokens pass `handle`; seller-scoped tokens may omit it.
Annotations the server declares
- title: Get Store Policies
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: true
list_ordersList a returning buyer's recent orders and their current fulfillment status — use this in a NEW session to answer 'did my order ship?' / 'where's my package?' when you don't have t…Reads text others writeNo findings
Why it is in this group
- The name "list_orders" says "list": a word for reading.
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it List a returning buyer's recent orders and their current fulfillment status — use this in a NEW session to answer 'did my order ship?' / 'where's my package?' when you don't have the original `session_id` from `checkout`. Requires the buyer's `buyer_token` (recover it via `request_buyer_code` + `verify_buyer` if you don't have one). Returns `{ orders, count }`, newest first; each order has `status` (`paid` | `shipped` | `delivered`), `items`, `amount_cents`, `placed_at`, and — once shipped — `tracking_number`, `carrier`, and a public `tracking_url`. **Pass `since` (an ISO-8601 timestamp from a previous check) to get only orders that changed since then** — surface those proactively ('your last order just shipped'). `order_id` identifies the order; `session_id` cross-references `order_status` for a single live checkout.
Annotations the server declares
- title: List Orders
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: true
list_sellersList all active sellers on the Kifly network.Reads text others writeNo findings
Why it is in this group
- The name "list_sellers" says "list": a word for reading.
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it List all active sellers on the Kifly network. **Requires a network token (kfn_live_…).** Returns each seller's handle, name, city, region, delivery coverage (`nationwide:true` or a `states` list), delivery fee, and catalog size. `delivery_coverage.cities` may be capped to a handful of entries — compare `cities.length` against `city_count`; if fewer, call `get_seller` for that seller's full city list. Use this to discover which sellers are available and which ship to a buyer's location before calling `get_seller` or `search_products`. **Pagination:** when `kifly:hasMore` is true, pass `kifly:nextCursor` as `cursor` to fetch the next page. Default page size is 20, max 50.
Annotations the server declares
- title: List Sellers
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: true
order_statusNo key needed for your own session: send the profile you checked out with.Reads text others writeNo findings
Why it is in this group
- The name "order_status" says "status": a word for reading.
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it No key needed for your own session: send the profile you checked out with. Check the status of a Stripe checkout session. Poll every 5 seconds after checkout until status is 'paid', 'shipped', or 'failed'. Returns order details (order_id, amount, items) when paid. When the seller marks the order as shipped, status becomes 'shipped' and tracking_number, carrier, and shipped_at are included — share these with the buyer.
Annotations the server declares
- title: Order Status
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: true
search_productsSearch or browse Kifly's product catalog across every seller on the network.Reads text others writeNo findings
Why it is in this group
- The name "search_products" says "search": a word for reading.
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
- untrusted-inputThe description's first sentence says "browse": it reads web pages, which anyone can write.
Description, as the server wrote it Search or browse Kifly's product catalog across every seller on the network. Multilingual semantic search (100+ languages); omit `q` to browse recent listings. Pass `q` as an array (up to 5) to try several phrasings in ONE call instead of N searches. Too many hits? Ask once with `facets: true`, then narrow with `delivers_to`, price, `category` or `seller_handle`; page with `cursor` when `kifly:hasMore`. Returns a JSON-LD ItemList. **Rules that matter before you read the response:** - Cart every product the buyer wants: checkout hands them to pay with the cart ready. `kifly:purchasable: false` is still buyable, paid on the seller's own site. `availability` is STOCK; `kifly:purchasable` is WHERE they pay. - On `availability:OutOfStock`, still show it if asked, say it is sold out, and never cart it (`add_to_cart` returns 409). - When a product has several size/style variants, ask the buyer ONE option axis at a time (`kifly:productOptions` gives the axes in the seller's order). Never recite the combination matrix. - On an empty result, read `kifly:emptyReason`: say nothing matched rather than guessing, then offer `kifly:suggestions` (related, NOT matches). Items with `kifly:offNetwork` are outside retailers': relay `kifly:affiliateDisclosure`, cart as usual. **Full field reference: resource `kifly://docs/search-response`** (seller map, delivery coverage, variants, capped fields, every `kifly:` extension). Fetch it once for field-level detail.
Annotations the server declares
- title: Search Catalog
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: true
This is not a safety rating, and no finding is not a safety guarantee. The groups and findings come from fixed checks of the tool definitions the server returned on the date shown, not from its code or what it does when called. How the checks work.
Exfil surface
Which tools read private data, which read text someone else can write, and which can send data out. One of each is a path a prompt injection can use.
72 paths in this server alone from private data, through text someone else wrote, to a way out. Denying 1 private-data tool breaks every one.
- Reads private data1
- Reads files, mail, messages, databases, secrets, calendars or repositories.
- Reads text others write18
- Brings in text someone else can write: web pages, inbound email, messages, issues and comments.
- Can send data out4
- Can carry data to people or systems: it sends, posts or publishes, or takes a recipient, channel or URL.
{
"permissions": {
"deny": [
"mcp__kifly__get_buyer_profile"
]
}
}Other servers in the same agent add their own tools to these paths. Audit your whole setup to see them together.
Install
Pinned to version 1.1.4. Values in angle brackets are yours to fill in.
claude mcp add --transport http kifly https://kifly.io/api/mcp --header 'Authorization: <your-authorization>'Run in a terminal.
Claude Code permissions
Allow the reads, ask before a change or a way out, deny the deletes. Paste into .claude/settings.json.
{
"permissions": {
"allow": [
"mcp__kifly__search_products",
"mcp__kifly__get_cart",
"mcp__kifly__get_buyer_profile",
"mcp__kifly__list_orders",
"mcp__kifly__get_policies",
"mcp__kifly__list_sellers",
"mcp__kifly__get_platform_limits",
"mcp__kifly__order_status",
"mcp__kifly__get_help"
],
"ask": [
"mcp__kifly__create_cart",
"mcp__kifly__add_to_cart",
"mcp__kifly__set_shipping_address",
"mcp__kifly__quick_buy",
"mcp__kifly__register_buyer",
"mcp__kifly__request_buyer_code",
"mcp__kifly__verify_buyer",
"mcp__kifly__save_buyer_address",
"mcp__kifly__submit_feedback",
"mcp__kifly__request_feature",
"mcp__kifly__get_seller"
],
"deny": [
"mcp__kifly__update_cart_item",
"mcp__kifly__checkout"
]
}
}Tools that only read are allowed, tools that change things ask first, tools that delete or cancel are denied. A read that can send data out (it takes a URL, say) asks first too. It assumes the server is installed as kifly. Review it before you use it.
Capability tags behind 19 rules
- mcp__kifly__search_products untrusted-input
- mcp__kifly__create_cart untrusted-input
- mcp__kifly__add_to_cart untrusted-input
- mcp__kifly__get_cart untrusted-input
- mcp__kifly__update_cart_item untrusted-input
- mcp__kifly__set_shipping_address untrusted-input, outbound
- mcp__kifly__quick_buy untrusted-input, outbound
- mcp__kifly__checkout untrusted-input
- mcp__kifly__register_buyer untrusted-input
- mcp__kifly__request_buyer_code untrusted-input
- mcp__kifly__verify_buyer untrusted-input
- mcp__kifly__get_buyer_profile private-data, untrusted-input
- mcp__kifly__list_orders untrusted-input
- mcp__kifly__save_buyer_address untrusted-input, outbound
- mcp__kifly__submit_feedback outbound
- mcp__kifly__get_seller untrusted-input
- mcp__kifly__get_policies untrusted-input
- mcp__kifly__list_sellers untrusted-input
- mcp__kifly__order_status untrusted-input