Pular para o conteúdo

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 ou x-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.


Caso de usoPorta recomendada
Claude Desktop, ChatGPT, Cursor conectados ao seu workspaceMCP (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 GaragemNenhuma (use webhooks; busque detalhe via REST ou MCP+API key)
Agente configurado dentro do Garagem em /agentesNem uma nem outra — o agente roda internamente com política própria

A mesma chave de Configurações → Desenvolvedor → API Keys autentica /api/mcp:

Janela do terminal
# Bearer
curl -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 resolveSubject do REST). roleId na 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 libera mcp.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 === false também bloqueia a chave.

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/mcp

Caminho mínimo:

  1. Cole o URL acima no campo “MCP server URL” / “Custom connector” do cliente.
  2. O cliente faz POST /api/auth/oauth2/register por baixo dos panos e recebe um client_id novo.
  3. 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.
  4. O cliente recebe um code, troca por access_token e está conectado.

Não é necessário copiar token, secret ou client ID. O OAuth 2.1 + PKCE cuida disso.

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.

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 serve apenas para casos específicos:

CasoPor quê
Vincular a um agenteA conexão passa a representar um agente de /agentes. Cada chamada herda o agentId e aparece no histórico do agente.
Restringir ferramentasDCR 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 surfaceHabilita mcp.raw.invoke_procedure (qualquer procedure que você consegue na UI). É opt-in explícito — DCR nunca pede esse modo.
Cliente sem suporte a DCRIntegrações server-to-server, parceiros, scripts custom. Você gera client_id (e secret, se for service) e configura no cliente.
Perfil diferente do donoLimitar 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:

TipoExemplotoken_endpoint_auth_methodTem client_secret?Como prova identidade no token endpoint
PúblicoClaude Desktop, Cursor, ChatGPT, app móvelnoneNãoPKCE (code_verifier)
ConfidencialBackend server-to-server, integraçõesclient_secret_basic ou _postSimclient_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.

Dois endpoints públicos (sem autenticação) deixam você inspecionar o servidor antes do handshake:

Janela do terminal
# 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 input
curl https://app.garagem.ai/api/mcp/.well-known/tools

A descoberta OAuth segue os RFCs padrão e está em três well-known endpoints:

Janela do terminal
# Resource metadata (RFC 9728) — aponta pro authorization server
curl https://app.garagem.ai/.well-known/oauth-protected-resource
# Authorization server metadata (RFC 8414) — token endpoint, JWKS, scopes
curl 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-configuration

O 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.ai faz o OAuth iniciar (porque o PRM está no root) mas as tool calls falham depois, porque o root não fala JSON-RPC.


Scopes controlam quais domínios de ferramentas uma conexão pode acessar. O formato é tools:{dominio}:

ScopeO que libera
tools:allTodas as ferramentas de todos os domínios.
tools:crmCRM (negócios, tarefas, contatos, visitas, recomendações).
tools:messagingEnvio de mensagens, templates, flows.
tools:real-estateCatálogo de imóveis e anúncios (busca, criação, atualização, fotos).
tools:analyticsRelatórios e métricas.
tools:social-mediaPublicação e gerenciamento de comentários.
tools:knowledgeConsultas à 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.


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.


Em todos os casos, o URL é o mesmo: https://app.garagem.ai/api/mcp.

Custom connectors usando MCP remoto (em beta, disponível em todos os planos):

  1. Abra Settings → Connectors (https://claude.ai/settings/connectors).
  2. Clique Add custom connector.
  3. Cole https://app.garagem.ai/api/mcp no campo Remote MCP server URL.
  4. Não preencha Advanced settings (OAuth Client ID/Secret) — deixe em branco. O Claude faz DCR sozinho.
  5. 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.
Janela do terminal
claude mcp add --transport http garagem https://app.garagem.ai/api/mcp

Na 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)

Em Settings → Connectors → Add connector, informe https://app.garagem.ai/api/mcp. (platform.openai.com)

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.


O servidor expõe um catálogo curado de aproximadamente 40 ferramentas de alto nível, organizadas por domínio. Exemplos:

DomínioFerramentas típicas
crmcrm.deal.list, crm.deal.create, crm.deal.update, crm.task.create, crm.visit.schedule, crm.contact.search
messagingmessaging.send_message, messaging.send_photos, messaging.send_template, messaging.handoff_to_human, messaging.list_templates, messaging.list_flows
real-estatereal-estate.search_listings, real-estate.create_listing, real-estate.identify_property, real-estate.geocode_address, real-estate.get_area_pricing
analyticsanalytics.get_entity_metrics, analytics.get_pipeline_state, analytics.get_time_series, analytics.get_top_performers, analytics.get_team_login_activity
knowledgeknowledge.get_faq_answer
social-mediasocial-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.


O modo “Acesso completo ao surface” habilita duas ferramentas adicionais que transformam a conexão MCP em um equivalente da interface do Garagem:

FerramentaPropósito
mcp.raw.list_proceduresLista todas as operações (paths) que você pode invocar, filtradas pelo seu perfil. Aceita prefix, limit, offset, includeSchemas.
mcp.raw.invoke_procedureInvoca 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.

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.

  • 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_procedures e não são invocáveis via invoke_procedure. Essas permanecem disponíveis apenas na UI.

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.


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.


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/v1 onde 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.


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/v1 documenta 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.