MCP
Assistentes de IA (MCP)
Conecte Claude, ChatGPT, Gemini CLI, Cursor ou VS Code à sua loja pelo Model Context Protocol. O conector MCP expõe a mesma API /v1 como ferramentas: mesmos escopos, limites, idempotência e auditoria — nada que a API não permita.
O que é
MCP é o protocolo aberto que os assistentes de IA usam para chamar ferramentas de um serviço externo. O servidor MCP da TF Shop Cloud fica no mesmo host da plataforma e cada ferramenta é uma operação REST empacotada: list_orders chama GET /orders, set_prices chama POST /prices/batch. Nada passa por fora da API pública.
- Endpoint do lojista
https://tfshopcloud.com.br/mcp- Endpoint da loja (comprador)
https://tfshopcloud.com.br/s/{slug}/mcp- Transporte
- Streamable HTTP: JSON-RPC 2.0 por
POST, resposta JSON ou SSE. Versões de protocolo 2025-03-26 a 2026-07-28, negociadas noinitialize. - Autenticação
- OAuth 2.1 (authorization code + PKCE
S256). Tokens estáticos da loja não são aceitos. - Catálogo
- 23 ferramentas do lojista, 13 da loja, 5 recursos e 4 prompts
- Mesmos escopos. Uma ferramenta exige o mesmo escopo do endpoint que ela chama, e o assistente só vê as ferramentas que o token permite (
tools/listé filtrado por escopo). - Mesmas regras. Limite de requisições por token,
Idempotency-Keynas escritas, erros RFC 9457 e registro de chamadas com oapp_idda conexão — tudo herdado do gateway/v1. - Dados pessoais mascarados por padrão: nome, CPF/CNPJ, e-mail, telefone e endereço do comprador só aparecem com
orders.pii:read, que o lojista concede à parte.
Conectar
Em todos os clientes o caminho é o mesmo: informe a URL https://tfshopcloud.com.br/mcp, clique em conectar e entre no painel da loja para autorizar. Não há client id, segredo nem token para copiar — o cliente se identifica sozinho (CIMD ou registro dinâmico) e recebe tokens de curta duração.
- 1
Em Configurações → Conectores, clique em Adicionar conector personalizado. Em planos Team e Enterprise só proprietários adicionam conectores; cada pessoa conecta a própria conta depois.
- 2
Nome
TF Shop Cloude a URL abaixo. Deixe o cliente OAuth em identidade publicada do Claude / registro automático: não é preciso client id nem segredo.urlhttps://tfshopcloud.com.br/mcp - 3
Clique em Conectar. Abre o login do painel da loja (com verificação em duas etapas, se ativa) e depois a tela de consentimento: escolha a loja, confira os escopos e aprove.
- 4
De volta ao Claude, as ferramentas aparecem no menu de conectores da conversa. No modo Pesquisa o Claude chama ferramentas sem pedir aprovação — deixe ativas só as de leitura.
Autorização (OAuth 2.1)
Assistentes de IA só entram por OAuth 2.1: authorization code com PKCE S256, cliente identificado por CIMD (Client ID Metadata Document, preferido) ou por registro dinâmico (DCR), iss em toda resposta de autorização e refresh token com rotação. Tokens da loja (tfs_live_…) não são aceitos no /mcp; o fluxo é o mesmo dos apps parceiros.
- 1primeira chamada ao
/mcpsem token 401+WWW-Authenticate: Bearer resource_metadata=…- 2lê os metadados do recurso e do servidor de autorização (
/.well-known/…) - 3identifica-se por CIMD (
client_id= URL HTTPS) ou registra-se emPOST /oauth/register - 4abre o navegador em
GET /oauth/authorize: login no painel + consentimento 302 redirect_uri?code=…&state=…&iss=…- 5
POST /oauth/tokencomcode+code_verifier - access token (1 h) + refresh token (30 dias)
- 6
initialize,tools/list,tools/callcomAuthorization: Bearer - 7renova com
grant_type=refresh_token(o anterior é invalidado)
Endereços
- Metadados do recurso protegido (RFC 9728)
https://tfshopcloud.com.br/.well-known/oauth-protected-resource- Metadados do servidor de autorização (RFC 8414)
https://tfshopcloud.com.br/.well-known/oauth-authorization-server- Autorização (navegador)
GET https://tfshopcloud.com.br/oauth/authorize- Token (`application/x-www-form-urlencoded`)
POST https://tfshopcloud.com.br/oauth/token- Registro dinâmico (DCR, RFC 7591)
POST https://tfshopcloud.com.br/oauth/register- Revogação (RFC 7009)
POST https://tfshopcloud.com.br/oauth/revoke
O que os documentos declaram
O cliente confia nesses documentos, não nesta página. A resposta 401 aponta para os metadados do recurso; o resource ali (e no parâmetro resource do pedido) é a URL do MCP exatamente como o usuário digitou; o servidor de autorização é o mesmo host da plataforma.
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer error="invalid_token",
error_description="Authentication required",
resource_metadata="https://tfshopcloud.com.br/.well-known/oauth-protected-resource"{
"resource": "https://tfshopcloud.com.br/mcp",
"authorization_servers": [
"https://tfshopcloud.com.br"
],
"scopes_supported": [
"store:read",
"products:read",
"products:write",
"inventory:read",
"inventory:write",
"orders:read",
"orders:write",
"orders.pii:read",
"invoices:write",
"fulfillments:write",
"webhooks:manage"
],
"bearer_methods_supported": [
"header"
],
"resource_documentation": "https://tfshopcloud.com.br/developers/mcp"
}{
"issuer": "https://tfshopcloud.com.br",
"authorization_endpoint": "https://tfshopcloud.com.br/oauth/authorize",
"token_endpoint": "https://tfshopcloud.com.br/oauth/token",
"registration_endpoint": "https://tfshopcloud.com.br/oauth/register",
"revocation_endpoint": "https://tfshopcloud.com.br/oauth/revoke",
"response_types_supported": [
"code"
],
"grant_types_supported": [
"authorization_code",
"refresh_token"
],
"code_challenge_methods_supported": [
"S256"
],
"token_endpoint_auth_methods_supported": [
"none",
"client_secret_post"
],
"scopes_supported": [
"store:read",
"products:read",
"products:write",
"inventory:read",
"inventory:write",
"orders:read",
"orders:write",
"orders.pii:read",
"invoices:write",
"fulfillments:write",
"webhooks:manage"
],
"client_id_metadata_document_supported": true,
"authorization_response_iss_parameter_supported": true
}https://tfshopcloud.com.br/oauth/authorize
?response_type=code
&client_id=https%3A%2F%2Fclaude.ai%2Foauth%2Fclaude-code-client-metadata
&redirect_uri=http%3A%2F%2Flocalhost%3A52817%2Fcallback
&scope=store%3Aread%20products%3Aread%20orders%3Aread
&resource=https%3A%2F%2Ftfshopcloud.com.br%2Fmcp
&state=8f1c2e7a90b4
&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
&code_challenge_method=S256curl -X POST https://tfshopcloud.com.br/oauth/token \
-d grant_type=authorization_code \
-d code=SplxlOBeZQQYbYS6WxSbIA \
--data-urlencode "redirect_uri=http://localhost:52817/callback" \
--data-urlencode "client_id=https://claude.ai/oauth/claude-code-client-metadata" \
--data-urlencode "resource=https://tfshopcloud.com.br/mcp" \
-d code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk{
"access_token": "tfs_live_…",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "rt_…",
"scope": "store:read products:read orders:read",
"store_id": "st_volt"
}POST /oauth/register HTTP/1.1
Content-Type: application/json
{
"client_name": "Assistente ACME",
"redirect_uris": [
"https://assistente.exemplo.com.br/oauth/callback"
],
"grant_types": [
"authorization_code",
"refresh_token"
],
"response_types": [
"code"
],
"token_endpoint_auth_method": "none",
"application_type": "web"
}Validade
| Campo | Valor | Descrição |
|---|---|---|
| Código de autorização | 10 min | uso único; trocado em POST /oauth/token com o code_verifier |
| Access token | 1 h | expires_in na resposta; é um token tfs_live_… comum, com os escopos concedidos, ligado a uma loja |
| Refresh token | 30 dias | rotaciona a cada uso: o anterior é invalidado e um refresh já usado responde invalid_grant, o que faz o cliente pedir novo login |
| Carrinho do comprador (MCP da loja) | 7 dias | carrinhos anônimos criados por create_cart no MCP da loja |
Tela de consentimento
A tela é em português, no painel da loja. Mostra quem pede acesso (nome e URL do cliente), para qual loja (lojistas com várias lojas escolhem aqui — um token vale para uma loja) e os escopos pedidos, agrupados nos perfis abaixo. O cliente pode pedir menos escopos que um perfil; o lojista aprova o que foi pedido ou recusa.
Perfis de escopo
- Somente leitura readonlystore:readproducts:readinventory:readorders:read
- Leitura + catálogo e estoque catalogstore:readproducts:readproducts:writeinventory:readinventory:writeorders:read
- Operação completa (sem dados pessoais) operationsstore:readproducts:readproducts:writeinventory:readinventory:writeorders:readorders:writefulfillments:writeinvoices:write
orders.pii:read nunca entra num perfil: aparece destacado, com o aviso da LGPD e de transferência internacional — os dados do comprador saem do Brasil para o provedor do assistente. Conceda só se a política de privacidade da loja prevê esse uso.Escopo insuficiente
Se o assistente chama uma ferramenta cujo escopo não foi concedido, a resposta é 403 com WWW-Authenticate: Bearer error="insufficient_scope" e o escopo que falta: clientes compatíveis reabrem o consentimento pedindo só ele. Qualquer outro 403 é definitivo.
HTTP/1.1 403 Forbidden
WWW-Authenticate: Bearer error="insufficient_scope", scope="orders:write"Desconectar
401, fazendo o cliente pedir novo login. Clientes também podem chamar POST /oauth/revoke.Ferramentas do lojista
23 ferramentas, geradas do mesmo catálogo que o servidor usa. Chame get_store primeiro para saber a que loja o token pertence. search e fetch seguem a convenção do ChatGPT (pesquisa profunda) e funcionam em qualquer cliente. Os títulos são mostrados em português pelos clientes; as descrições, lidas pelo modelo, ficam em inglês.
Somente leitura não muda nada na loja. Altera dados cria ou atualiza registros de forma reversível. Ação sensível muda o que o cliente paga, o estoque, o status do pedido ou a NF-e — o assistente deve confirmar com o lojista antes de chamar, e os clientes mostram um pedido de aprovação. Dados pessoais marca ferramentas que devolvem dados do comprador (mascarados sem orders.pii:read).
| Ferramenta | Escopo | Tipo | Operação REST |
|---|---|---|---|
get_storeDados da lojaThe connected store: name, domain, legal entity (CNPJ), plan limits, NF-e issuer (tf_fiscal or erp), currency and time zone. Call it first to know which store the token belongs to. | store:read | somente leitura | GET / |
searchBuscar na lojaSearch products (title, SKU, GTIN) and orders (number, buyer name or e-mail when the token has orders.pii:read) of the store. Returns {results:[{id,title,url}]}; pass an id to fetch. | products:read | somente leituradados pessoais | — |
fetchAbrir itemFetch one object by the id returned from search: a product (with variants and stock) or an order (NF-e-ready payload, buyer data masked without orders.pii:read). Returns {id,title,text,url,metadata}. | products:read | somente leituradados pessoais | — |
list_productsListar produtosList products with variants, prices (integer centavos) and stock, filtered by status or updated_since; cursor pagination (limit ≤100). | products:read | somente leitura | GET / |
get_productVer produtoOne product with its variants, fiscal data (NCM optional), weight and dimensions. | products:read | somente leitura | GET / |
find_variants_by_skuBuscar por SKULook variants up by SKU (up to 100 SKUs) with price and stock. Use it before writing prices or stock. | products:read | somente leitura | GET / |
list_inventory_levelsVer estoqueStock levels by SKU: on_hand, reserved (unpaid orders) and available = on_hand − reserved. | inventory:read | somente leitura | GET / |
list_ordersListar pedidosList orders by status, updated_since or export_status (pending = paid orders this connection has not acknowledged yet). Test orders are excluded unless include_test=true. Buyer data is masked without orders.pii:read. | orders:read | somente leituradados pessoais | GET / |
get_orderVer pedidoOne order with lines, discounts and freight allocated per line, payment (Pix/card/boleto with NF-e codes), fiscal hints, invoice and fulfillment. Buyer data is masked without orders.pii:read. | orders:read | somente leituradados pessoais | GET / |
list_eventsEventos recentesEvents of the last 30 days (order.paid, invoice.authorized, fulfillment.shipped, inventory.updated…), thin payloads with ids only. Events whose actor.app_id is this connection were caused by you. | orders:read | somente leitura | GET / |
list_webhook_endpointsVer webhooksWebhook endpoints of this connection (read only: creating or deleting endpoints is done in the admin). | webhooks:manage | somente leitura | GET / |
create_productCriar produtoCreate a product with variants (unique SKUs, price > 0 in centavos). NCM is optional. New products start as draft unless status=active is requested and weight is set. | products:write | altera dadosidempotente | POST / |
update_productAlterar produtoUpdate title, description, status, fiscal data, weight or dimensions of a product (not prices or stock: use set_prices / set_inventory_levels). | products:write | altera dadosidempotente | PATCH / |
archive_productArquivar produtoArchive a product (hidden from the storefront, kept in orders and reports). Reversible from the admin. | products:write | ação sensívelidempotente | DELETE / |
set_pricesAlterar preçosSet the retail and compare-at price of up to 100 SKUs (integer centavos). Changes what shoppers pay immediately: confirm the SKUs and values with the merchant first. | products:write | ação sensívelidempotente | POST / |
set_inventory_levelsAjustar estoque (absoluto)Set the absolute on-hand quantity of up to 100 SKUs (after a stock count). Reserved units of unpaid orders are kept. Wrong values cause overselling or lost sales: confirm with the merchant first. | inventory:write | ação sensívelidempotente | POST / |
adjust_inventoryAjustar estoque (±)Add or remove units of up to 100 SKUs with a reason (receipt, loss, correction). Not idempotent by nature: pass the same idempotency_key to retry safely. | inventory:write | ação sensível | POST / |
acknowledge_orderMarcar pedido como importadoMark an order as imported by this connection (optionally with your external id). Idempotent: acknowledging again returns the first acknowledgement. | orders:write | altera dadosidempotente | POST / |
request_order_cancellationCancelar / pedir cancelamentoCancel an unpaid order at once, or register a cancellation request on a paid order for the merchant to decide (refunds always happen in the admin through C6). Confirm the order number with the merchant first. | orders:write | ação sensível | POST / |
create_fulfillmentMarcar como enviadoShip an order with carrier, service and tracking code (Correios codes are validated). Requires an authorised NF-e or DC-e. Sends the shipped e-mail to the buyer. | fulfillments:write | ação sensívelidempotentedados pessoais | POST / |
mark_deliveredMarcar como entregueMark a shipped order as delivered. | fulfillments:write | altera dadosidempotente | POST / |
register_erp_invoiceRegistrar NF-e do ERPRegister the NF-e issued by the merchant's ERP for an order: 44-digit access key (check digit, model 55, issuer = store CNPJ), optional XML/DANFE URLs. Rejected (409) when the store issues its own NF-e through TF Fiscal. Idempotent by access key. | invoices:write | ação sensívelidempotente | POST / |
cancel_erp_invoiceRegistrar cancelamento de NF-eReport that an NF-e registered from the ERP was cancelled at SEFAZ. | invoices:write | ação sensívelidempotente | POST / |
POST /mcp HTTP/1.1
Host: tfshopcloud.com.br
Authorization: Bearer tfs_live_…
Content-Type: application/json
Accept: application/json, text/event-stream
MCP-Protocol-Version: 2025-11-25
{
"jsonrpc": "2.0",
"id": 7,
"method": "tools/call",
"params": {
"name": "list_orders",
"arguments": {
"status": "paid",
"export_status": "pending",
"limit": 20
}
}
}O que não existe como ferramenta
Recursos e prompts
Recursos são documentos estáveis e somente leitura que o cliente anexa ao contexto sem gastar uma chamada de ferramenta. Prompts são fluxos prontos (o loop do ERP e as regras de conciliação dos guias) que o usuário invoca pelo nome; cada um lista os escopos que vai usar.
| URI | Nome | Descrição |
|---|---|---|
tfshop://store | Store profile | The connected store (same as get_store). |
tfshop://openapi | OpenAPI 3.1 document of the public API | Generated from the operation catalog; JSON. |
tfshop://scopes | API scopes | Every scope with what it allows; PII scopes flagged. |
tfshop://events | Webhook event catalog | Event types and the scope each one needs. |
tfshop://docs/{page} | Developer docs page | pedidos-erp | catalogo | webhooks | erros | limites | sandbox (pt-BR text). |
| Prompt | Descrição | Escopos usados |
|---|---|---|
daily_sales_briefResumo de vendas do dia | Summarise yesterday's and today's paid orders, revenue, average ticket, top products and orders waiting for NF-e or shipping. | orders:read |
erp_sync_paid_ordersSincronizar pedidos pagos com o ERP | Walk the paid orders not yet acknowledged: fetch each, hand it to the ERP, acknowledge with the external id, register the NF-e when the store's issuer is the ERP, then ship. Skip events caused by this connection. | orders:readorders:write |
reconcile_stock_by_skuConferir estoque por SKU | Compare a list of SKUs and counted quantities with the store's levels and prepare the absolute set_inventory_levels call for the merchant to approve. | inventory:readinventory:write |
nfe_readiness_checkChecar pendências de NF-e | Find paid orders without NF-e, products missing NCM (when the store issues through TF Fiscal) and orders waiting for the ERP's NF-e. | orders:readproducts:readstore:read |
MCP da loja (compradores)
Cada loja publicada tem um endpoint MCP anônimo, para que assistentes ajudem o comprador a descobrir produtos, montar o carrinho e ir para o checkout. Sem login e sem token; limite de requisições por IP; só dados públicos (preços de varejo em centavos, políticas, frete por CEP). Lojas pausadas ou com assinatura inativa não respondem.
- URL por slug
https://tfshopcloud.com.br/s/{slug}/mcp- URL no domínio próprio
https://{store-domain}/mcp- Autenticação
- Anônima (sem OAuth); limite por IP
- Carrinho do comprador (MCP da loja)
- 7 dias
O slug é o mesmo da loja em /s/{slug}; com domínio próprio, o mesmo servidor responde em https://{store-domain}/mcp. Os nomes das ferramentas seguem o formato do UCP (search_catalog, get_product, create_cart, update_cart), para que assistentes já integrados a outras lojas usem o mesmo vocabulário.
| Ferramenta | Tipo |
|---|---|
get_store_infoSobre a lojaStore name, legal entity (CNPJ, as Brazilian law requires), contact, payment methods (Pix, card instalments, boleto), shipping origin and policy summaries. | somente leitura |
search_catalogBuscar produtosSearch the store's active products by text, category or collection; cursor pagination. Prices are the public retail prices in BRL (integer centavos); wholesale and member prices are never returned. | somente leitura |
get_productVer produtoOne product by id or handle: description, images, variants with price and availability, dimensions, size chart and compliance attributes. | somente leitura |
list_categoriesCategoriasThe store's category tree (up to 3 levels). | somente leitura |
list_collectionsColeçõesPublished collections (campaigns, launches, best sellers). | somente leitura |
ask_store_policiesPerguntar sobre políticasAnswer a question from the store's own policy pages (returns, exchanges, shipping, privacy, payment) with the policy text and its URL. Does not invent policies. | somente leitura |
lookup_cepConsultar CEPResolve a Brazilian CEP to street, district, city, state and IBGE code. | somente leitura |
quote_shippingCalcular freteShipping options (carrier, service, price in centavos, business days) for a CEP and a list of variant quantities, including free-shipping thresholds. | somente leitura |
create_cartCriar carrinhoCreate a cart for this store with variant quantities. Returns a cart_id to use in the next calls (carts expire after 7 days). | altera dados |
get_cartVer carrinhoCart lines, subtotal and discounts; shipping is quoted separately by CEP. | somente leitura |
update_cartAlterar carrinhoReplace the cart lines (full replacement, like UCP update_cart). Send an empty list to clear it. | altera dadosidempotente |
create_checkout_handoffIr para o checkoutReturn the store's checkout URL pre-filled with the cart (and the CEP, if given). The shopper finishes the order and pays (Pix, card instalments or boleto) on the store's own page: no payment data goes through the assistant. | somente leitura |
track_orderRastrear pedidoShipping status and events for a tracking code (no buyer data). | somente leitura |
O que nunca acontece aqui
create_checkout_handoff devolve a URL do checkout da loja com o carrinho preenchido; o comprador finaliza e paga (Pix, cartão, boleto) na página da loja. Nenhum dado de pagamento, endereço ou pedido de terceiros passa pelo assistente, e o carrinho expira em 7 dias.As páginas da loja já publicam JSON-LD (Product, Offer, BreadcrumbList): assistentes que navegam pela web leem preço e disponibilidade sem MCP. O MCP acrescenta busca, carrinho, frete por CEP e políticas em formato estruturado.
Segurança e LGPD
- Nada além da API. O MCP não tem canal privado: se uma operação não existe em
/v1, não existe como ferramenta. Dinheiro, fiscal e ações irreversíveis ficam no painel. - Dados pessoais do comprador são mascarados sem
orders.pii:read. Ao conceder esse escopo a um assistente, o lojista autoriza uma transferência internacional de dados: a tela de consentimento diz isso com todas as letras, e a política de privacidade da loja deve prever o uso. - Confirmação antes de agir. Toda ferramenta traz anotações (
readOnlyHint,destructiveHint,idempotentHint), e as sensíveis dizem na descrição “confirme com o lojista”. Os clientes mostram um pedido de aprovação; no modo Pesquisa do Claude isso não acontece — mantenha só leitura. - Limites herdados. Cada conexão é um aplicativo com seu token: 5 requisições por segundo (picos de 50), as mesmas do
/v1. Chamadas em excesso recebem429e o assistente deve esperar. - Auditoria. Cada chamada entra em Aplicativos e API → Registro de chamadas com o cliente, a ferramenta e o resultado; escritas aparecem nos eventos com o
actor.app_idda conexão, como qualquer app. - Injeção de prompt. Títulos de produtos, observações de pedidos e nomes de compradores são dados, não instruções. O servidor devolve esses textos sem alterá-los; trate resultados de ferramentas como conteúdo não confiável no assistente.
- Revogação. Desconectar no painel, remover da loja o usuário que consentiu ou a TF suspender o cliente revoga os tokens da conexão na hora.
Limites
- Tamanho dos resultados. O Claude (web e desktop) aceita cerca de 150 mil caracteres por resultado e 240 s por chamada; o Claude Code corta em 25 mil tokens (
MAX_MCP_OUTPUT_TOKENS) e salva em arquivo textos acima de 50 mil caracteres. Por isso as listas paginam:limit≤ 100 enext_cursorpara continuar. - Filtre no servidor. Use
status,updated_since,export_statuse listas de SKUs em vez de listar tudo;searchdevolve só id, título e URL — chamefetchno item certo. - Chamadas curtas. Cada ferramenta corresponde a uma requisição
/v1; não há operações longas. Para lotes grandes, divida em chamadas de até 100 SKUs. - Contexto. Nomes e descrições são curtos, e o servidor publica
instructionsnoinitializecom a loja conectada, a unidade monetária (centavos) e a regra “leitura imediata, escrita só com confirmação”.