MCP — Model Context Protocol
Esta seção documenta como conectar clientes de LLM (Claude Desktop, ChatGPT, Cursor, Claude Code, agentes customizados) ao Garagem via Model Context Protocol.
MCP é o segundo “porta de entrada” do Garagem, paralelo ao REST (/api/v1):
/api/v1— API REST com autenticação por API key. Para scripts, parceiros, integrações WordPress, automações estilo Zapier. Superfície completa (OpenAPI)./api/mcp— Servidor MCP. Primário: OAuth 2.1 para clientes LLM. Também aceita a mesma API key permanente de/desenvolvedor(Bearer oux-api-key) para automações headless que falam o protocolo MCP — sem consentimento no browser e sem reconnect.
Ambas as portas usam exatamente o mesmo modelo de permissões (RBAC) que a interface do Garagem. Um usuário com perfil corretor faz as mesmas coisas em qualquer uma das duas portas.
🎯 Quando usar MCP vs /api/v1
Seção intitulada “🎯 Quando usar MCP vs /api/v1”| Caso de uso | Porta recomendada |
|---|---|
| Claude Desktop, ChatGPT, Cursor conectados ao seu workspace | MCP (OAuth) |
| Claude Code ou agente rodando no seu terminal operando o Garagem por você | MCP (modo “Acesso completo”, OAuth) |
| Automação headless que já fala MCP (webhook → tool call) | MCP com API key permanente |
| Script Node/Python server-to-server (cron, ETL, sincronização) | /api/v1 |
| Plugin WordPress, integração com site externo | /api/v1 |
| Webhook/listener recebendo eventos do Garagem | Nenhuma (use webhooks; busque detalhe via REST ou MCP+API key) |
Agente configurado dentro do Garagem em /agentes | Nem uma nem outra — o agente roda internamente com política própria |
API key permanente no MCP (headless)
Seção intitulada “API key permanente no MCP (headless)”A mesma chave de Configurações → Desenvolvedor → API Keys autentica /api/mcp:
# Bearercurl -X POST "https://app.garagem.ai/api/mcp" \ -H "Authorization: Bearer sua_api_key" \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
# ou x-api-key (+ x-tenant-id opcional, se a chave cobrir mais de um tenant)curl -X POST "https://app.garagem.ai/api/mcp" \ -H "x-api-key: sua_api_key" \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'Comportamento:
- Age como o usuário que criou a chave (mesmo
resolveSubjectdo REST).roleIdna metadata da chave vira teto (interseção com as permissões reais do usuário) — nunca escala. - Libera o catálogo MCP curado (
toolAccessMode: all). Não liberamcp.raw.invoke_procedure/surface:full— esse escape hatch continua só via OAuth com consentimento admin. - Rate limit: mesmo teto Better Auth da API key (1000 req/h, por chave). Esgotamento devolve 429, não 401.
- Kill switch:
tenantConfig.mcpEnabled === falsetambém bloqueia a chave.
🔌 Conectando — caminho padrão
Seção intitulada “🔌 Conectando — caminho padrão”Você não precisa criar nada em /desenvolvedor para conectar Claude, Cursor ou ChatGPT. Esses clientes implementam Dynamic Client Registration (DCR) e fazem o handshake sozinhos. Basta o URL:
https://app.garagem.ai/api/mcpCaminho mínimo:
- Cole o URL acima no campo “MCP server URL” / “Custom connector” do cliente.
- O cliente faz
POST /api/auth/oauth2/registerpor baixo dos panos e recebe umclient_idnovo. - Ele abre o navegador na página de consent do Garagem. Você faz login (se ainda não estava) e vê a tela de autorização — ela mostra com qual usuário e em qual workspace você está autorizando, antes de você clicar Aceitar.
- O cliente recebe um
code, troca poraccess_tokene está conectado.
Não é necessário copiar token, secret ou client ID. O OAuth 2.1 + PKCE cuida disso.
Onde ver e revogar suas conexões
Seção intitulada “Onde ver e revogar suas conexões”Cada usuário gerencia as próprias conexões em Configurações → Segurança → Aplicações conectadas. Lá aparece o app conectado, quando, quais permissões e o botão de desconectar.
A tela de Configurações → Desenvolvedor → Conexões MCP continua existindo para administradores que precisam pré-registrar conexões com escopo customizado, vincular a agentes, ou liberar acesso completo ao surface — esses casos estão na próxima seção.
Vinculação ao workspace (multi-tenant)
Seção intitulada “Vinculação ao workspace (multi-tenant)”A conexão fica amarrada ao workspace ativo no momento do consent. Quando você clica Aceitar, o servidor lê seu activeOrganizationId da sessão, busca o tenant correspondente e grava no metadata do OAuth client. Toda chamada MCP via essa conexão atua naquele tenant — mesmo que você troque de workspace na UI depois.
Para conectar o mesmo cliente (ex.: Claude) a múltiplos workspaces, você precisa de uma conexão por workspace: troque pro workspace alvo na UI, adicione o connector no Claude (ele cria um client_id novo via DCR), autorize. Cada uma fica visível em Segurança → Aplicações conectadas com badge do workspace.
Pré-registrar uma conexão (avançado)
Seção intitulada “Pré-registrar uma conexão (avançado)”Pré-registrar serve apenas para casos específicos:
| Caso | Por quê |
|---|---|
| Vincular a um agente | A conexão passa a representar um agente de /agentes. Cada chamada herda o agentId e aparece no histórico do agente. |
| Restringir ferramentas | DCR cria com acesso ao catálogo curado padrão. Pra liberar só crm.* ou só uma lista explícita, pré-registre com toolPolicy. |
| Acesso completo ao surface | Habilita mcp.raw.invoke_procedure (qualquer procedure que você consegue na UI). É opt-in explícito — DCR nunca pede esse modo. |
| Cliente sem suporte a DCR | Integrações server-to-server, parceiros, scripts custom. Você gera client_id (e secret, se for service) e configura no cliente. |
| Perfil diferente do dono | Limitar a conexão ao perfil corretor mesmo logado como proprietario, por exemplo. |
Em Configurações → Desenvolvedor → Conexões MCP, abra a seção “Pré-registrar conexão (avançado)”. Para clientes que já suportam DCR (Claude/Cursor/ChatGPT), você cola o client_id gerado em Advanced settings do diálogo “Add custom connector” do cliente — assim ele pula o DCR e usa o que você criou.
🔐 Tipos de cliente — público vs confidencial
Seção intitulada “🔐 Tipos de cliente — público vs confidencial”OAuth 2.1 distingue dois tipos pelo que o cliente consegue (ou não) guardar em segredo:
| Tipo | Exemplo | token_endpoint_auth_method | Tem client_secret? | Como prova identidade no token endpoint |
|---|---|---|---|---|
| Público | Claude Desktop, Cursor, ChatGPT, app móvel | none | Não | PKCE (code_verifier) |
| Confidencial | Backend server-to-server, integrações | client_secret_basic ou _post | Sim | client_secret |
Cliente público não pode guardar segredo (qualquer um com acesso ao binário extrai), por isso PKCE é obrigatório: o cliente gera um code_verifier aleatório, manda o hash (code_challenge) na request de authorize, e o code_verifier em texto claro na request de token. O servidor confere SHA256(code_verifier) == code_challenge — prova de posse sem secret.
Clientes registrados via DCR no Garagem ficam como públicos por padrão. Service clients (criados pela tela de pré-registro com tipo service) ficam como confidenciais com secret gerado uma única vez.
Descobrindo capacidades antes de conectar
Seção intitulada “Descobrindo capacidades antes de conectar”Dois endpoints públicos (sem autenticação) deixam você inspecionar o servidor antes do handshake:
# Scopes disponíveis (tools:{dominio} + tools:all)curl https://app.garagem.ai/api/mcp/.well-known/scopes
# Catálogo de ferramentas públicas com JSON Schema de inputcurl https://app.garagem.ai/api/mcp/.well-known/toolsA descoberta OAuth segue os RFCs padrão e está em três well-known endpoints:
# Resource metadata (RFC 9728) — aponta pro authorization servercurl https://app.garagem.ai/.well-known/oauth-protected-resource
# Authorization server metadata (RFC 8414) — token endpoint, JWKS, scopescurl https://app.garagem.ai/.well-known/oauth-authorization-server
# OpenID Connect discovery (id_token claims, alg, etc.)curl https://app.garagem.ai/.well-known/openid-configurationO URL do servidor MCP precisa ser
https://app.garagem.ai/api/mcp. Os well-known acima cobrem a descoberta de OAuth, não a do endpoint MCP — o transporte fica em/api/mcp. Colar sóhttps://app.garagem.aifaz o OAuth iniciar (porque o PRM está no root) mas as tool calls falham depois, porque o root não fala JSON-RPC.
🎚 Scopes
Seção intitulada “🎚 Scopes”Scopes controlam quais domínios de ferramentas uma conexão pode acessar. O formato é tools:{dominio}:
| Scope | O que libera |
|---|---|
tools:all | Todas as ferramentas de todos os domínios. |
tools:crm | CRM (negócios, tarefas, contatos, visitas, recomendações). |
tools:messaging | Envio de mensagens, templates, flows. |
tools:real-estate | Catálogo de imóveis e anúncios (busca, criação, atualização, fotos). |
tools:analytics | Relatórios e métricas. |
tools:social-media | Publicação e gerenciamento de comentários. |
tools:knowledge | Consultas à base de conhecimento / FAQ. |
A lista completa e atual está em GET /api/mcp/.well-known/scopes.
Scopes são coarse-grained — dizem em que domínio a conexão pode atuar, não o que o usuário pode fazer. O que o usuário pode fazer vem do perfil (RBAC) dele na plataforma, que é checado a cada chamada.
Quem pode conectar
Seção intitulada “Quem pode conectar”Por padrão, qualquer membro do workspace autoriza o MCP com a própria conta. O que a conexão consegue fazer continua sendo o RBAC desse perfil.
Um gestor restringe quem conecta em Configurações → Desenvolvedor → Conexões MCP:
- Restringir por perfil desligado — qualquer membro.
- Restringir por perfil ligado — só os perfis marcados passam da tela de autorização e das chamadas seguintes. Quem já tinha conectado e ficou de fora para na próxima chamada.
A mesma tela lista as pessoas que autorizaram um cliente neste workspace e desconecta cada uma (apaga consentimento e tokens). Cada pessoa também desconecta os próprios apps em Configurações → Segurança → Aplicações conectadas.
O interruptor “Permitir conexões MCP” continua valendo para o workspace inteiro, inclusive para os perfis liberados e para chaves de API.
🖥 Conectando a partir de clientes populares
Seção intitulada “🖥 Conectando a partir de clientes populares”Em todos os casos, o URL é o mesmo: https://app.garagem.ai/api/mcp.
Claude (Desktop, Web e Mobile)
Seção intitulada “Claude (Desktop, Web e Mobile)”Custom connectors usando MCP remoto (em beta, disponível em todos os planos):
- Abra Settings → Connectors (
https://claude.ai/settings/connectors). - Clique Add custom connector.
- Cole
https://app.garagem.ai/api/mcpno campo Remote MCP server URL. - Não preencha Advanced settings (OAuth Client ID/Secret) — deixe em branco. O Claude faz DCR sozinho.
- Clique Add. Na primeira interação que use o connector, o Claude abre uma aba de autorização — faça login no Garagem e clique Aceitar.
Claude Code (CLI)
Seção intitulada “Claude Code (CLI)”claude mcp add --transport http garagem https://app.garagem.ai/api/mcpNa primeira tool call, o Claude Code abre o navegador para o consent. Vale habilitar a conexão como “Acesso completo ao surface” (em /desenvolvedor antes de adicionar) se quiser dar ao Claude Code o equivalente da UI completa.
Em Settings → MCP → New server, cole https://app.garagem.ai/api/mcp. Cursor cuida do OAuth automaticamente. (docs.cursor.com)
ChatGPT
Seção intitulada “ChatGPT”Em Settings → Connectors → Add connector, informe https://app.garagem.ai/api/mcp. (platform.openai.com)
Cliente customizado (TypeScript/Python)
Seção intitulada “Cliente customizado (TypeScript/Python)”Qualquer biblioteca que implemente MCP sobre HTTP (ex.: @modelcontextprotocol/sdk) consegue se conectar passando o URL, fazendo o fluxo OAuth e listando as ferramentas via tools/list. Se o seu cliente não suporta DCR, pré-registre uma conexão em /desenvolvedor para gerar client_id (e client_secret, se service) manualmente e configure no cliente.
🛠 Ferramentas disponíveis
Seção intitulada “🛠 Ferramentas disponíveis”O servidor expõe um catálogo curado de aproximadamente 40 ferramentas de alto nível, organizadas por domínio. Exemplos:
| Domínio | Ferramentas típicas |
|---|---|
crm | crm.deal.list, crm.deal.create, crm.deal.update, crm.task.create, crm.visit.schedule, crm.contact.search |
messaging | messaging.send_message, messaging.send_photos, messaging.send_template, messaging.handoff_to_human, messaging.list_templates, messaging.list_flows |
real-estate | real-estate.search_listings, real-estate.create_listing, real-estate.identify_property, real-estate.geocode_address, real-estate.get_area_pricing |
analytics | analytics.get_entity_metrics, analytics.get_pipeline_state, analytics.get_time_series, analytics.get_top_performers, analytics.get_team_login_activity |
knowledge | knowledge.get_faq_answer |
social-media | social-media.list_recent_posts, social-media.publish_post, social-media.reply_to_comment |
A lista completa, com descrição e JSON Schema de cada input, está em GET /api/mcp/.well-known/tools — use esse endpoint como fonte canônica. A documentação em markdown pode ficar desatualizada; o endpoint nunca fica.
🚀 Acesso completo ao surface (avançado)
Seção intitulada “🚀 Acesso completo ao surface (avançado)”O modo “Acesso completo ao surface” habilita duas ferramentas adicionais que transformam a conexão MCP em um equivalente da interface do Garagem:
| Ferramenta | Propósito |
|---|---|
mcp.raw.list_procedures | Lista todas as operações (paths) que você pode invocar, filtradas pelo seu perfil. Aceita prefix, limit, offset, includeSchemas. |
mcp.raw.invoke_procedure | Invoca qualquer operação pelo path retornado acima, passando o input correspondente. |
Juntas, essas duas ferramentas permitem ao LLM “qualquer coisa que você conseguiria fazer clicando na UI” — sem depender de cada operação ter sido previamente projetada como uma ferramenta nomeada.
Como usar
Seção intitulada “Como usar”LLM: Preciso listar todas as tarefas pendentes do João
1) Chama mcp.raw.list_procedures com { prefix: "crm.tasks" } Resposta inclui: crm.tasks.list, crm.tasks.get, crm.tasks.update, ...
2) Chama mcp.raw.invoke_procedure com: { path: "crm.tasks.list", input: { status: "pending", assignedToId: "..." } }
3) Recebe a lista de tarefas no mesmo formato da UI.Na prática, clientes modernos (Claude Desktop, Cursor, Claude Code) descobrem esse fluxo automaticamente — você só precisa pedir em linguagem natural.
Limites importantes
Seção intitulada “Limites importantes”- RBAC continua valendo. Se o seu perfil é
corretor, você não consegue criar usuários, mexer em configurações de tenant, nem nada fora do que a UI permitiria. Acesso completo significa “tudo que você consegue fazer na UI”, não “tudo que o sistema consegue fazer”. - Não disponível para agentes. Conexões vinculadas a um agente (seja pelo modo “Vincular a um agente” ou por agentes internos do
/agentes) não podem usar essas duas ferramentas. Agentes autônomos ficam restritos a ferramentas explicitamente liberadas na política deles. Essa restrição é estrutural — não é contornável por configuração. - Rate limits se aplicam da mesma forma que à UI.
- Nem tudo é procedure. Operações que não são chamadas request/response (fluxos de upload de arquivo, streams em tempo real, autenticação/sessão) não aparecem em
list_procedurese não são invocáveis viainvoke_procedure. Essas permanecem disponíveis apenas na UI.
Quando habilitar
Seção intitulada “Quando habilitar”Habilite “Acesso completo” para conexões onde um humano está no comando — Claude Desktop, Cursor, ChatGPT, Claude Code. Deixe desabilitado (modo Padrão) para agentes, automações não-supervisionadas e conexões de parceiros.
⏱ Rate limits
Seção intitulada “⏱ Rate limits”Há dois controles independentes:
- Autenticação da API key — a verificação é reutilizada por até 60 segundos no processo, sem armazenar a chave bruta. Tenant, organização, RBAC, política da ferramenta e o kill switch do MCP continuam sendo reavaliados em cada chamada.
- Execução da capability — o orçamento padrão é por tenant + principal + ferramenta: leituras até 120 chamadas/minuto; escritas até 60 chamadas/minuto, salvo política específica mais restritiva.
Quando uma ferramenta atinge o orçamento de execução, o resultado MCP retorna o problema estruturado RATE_LIMITED, com retryAfterSeconds, limit e remaining. Clientes devem usar esses campos para backoff; não interprete rate limiting como credencial inválida e não repita a mesma consulta sem necessidade.
🚫 O que não está em MCP
Seção intitulada “🚫 O que não está em MCP”Algumas capacidades do Garagem intencionalmente não são expostas como ferramentas MCP:
- Autenticação e sessão — login, logout, 2FA. Função do próprio OAuth, não de ferramentas.
- Configuração administrativa do tenant — gestão de usuários, perfis, faturamento. Operações de alto risco; use a UI.
- Upload direto de arquivos — o fluxo de anexar documentos, fotos de imóveis, etc. não tem formato MCP natural hoje. Use a UI ou
/api/v1onde aplicável. - Wizards multi-etapa — criação guiada de imóvel, onboarding. O fluxo de passos e validações cruzadas não mapeia bem para chamadas isoladas.
- Streams em tempo real — atualizações ao vivo de mensagens, notificações. MCP é request/response; use webhooks para receber eventos.
- Endpoints do próprio painel de desenvolvedor — criar/listar chaves de API e conexões MCP. Essas configuram o surface, portanto não são chamáveis de dentro dele.
Se você precisa de alguma dessas capacidades a partir de fora da UI, a rota é /api/v1 com uma API key de perfil apropriado.
🔄 Como MCP se relaciona com /api/v1
Seção intitulada “🔄 Como MCP se relaciona com /api/v1”As duas portas coexistem e usam o mesmo modelo de permissão:
- Ambas chegam no mesmo conjunto de operações internas.
- Ambas respeitam o RBAC do usuário autenticado.
- MCP é opt-in por operação — uma procedure só vira ferramenta se foi explicitamente liberada.
/api/v1documenta endpoints específicos para as operações mais comuns de CRUD.- “Acesso completo ao surface” em MCP permite ao cliente invocar qualquer procedure que você poderia na UI, via as duas ferramentas
mcp.raw.*.
Se você está construindo uma integração server-to-server, prefira /api/v1. Se você está plugando um LLM conversacional no Garagem, prefira MCP.
📚 Próximos passos
Seção intitulada “📚 Próximos passos”- Guia Rápido — primeira requisição na API REST
- Exemplos Práticos — casos de uso combinando REST e MCP
- Webhooks e Eventos — receber notificações em tempo real