A transição definitiva da arquitetura corporativa para o paradigma Agent-first através do padrão aberto Model Context Protocol hospedado na infraestrutura nativa da Salesforce.

Durante mais de vinte anos, nós construímos o coração operacional das maiores corporações do mundo dentro de classes Apex e, no final das contas, trancamos tudo atrás de uma tela no navegador.
Se um diretor quisesse avaliar o risco de uma conta estratégica, calcular a margem líquida de um contrato complexo ou rotear um caso prioritário, um operador humano precisava fazer login no Salesforce, esperar o Lightning Experience carregar, abrir abas, preencher formulários e clicar em botões. Se a empresa quisesse automação, construíamos integrações REST pesadas. Criávamos APIs sob medida. Consumíamos semanas alinhando contratos JSON com times de backend.
O jogo virou.
Com agentes autônomos operando diretamente no terminal de engenharia (Claude Code), em IDEs de desenvolvimento (Cursor) ou em chats executivos (Claude Desktop, ChatGPT e Slack), a interface visual virou gargalo. É o fim da era UI-first.
Para responder a essa ruptura, a Salesforce lançou a iniciativa Headless 360 e os Salesforce Hosted MCP Servers.
Baseados no Model Context Protocol (MCP) — o padrão aberto mantido pela indústria de IA para descoberta e orquestração de ferramentas por LLMs —, os servidores MCP gerenciados pela Salesforce permitem que qualquer agente de inteligência artificial converse diretamente com suas classes Apex. Sem contêineres intermediários no Heroku ou na AWS. Sem web scraping. Sem gambiarras de automação de navegador.
Neste artigo prático, vamos abrir o capô dessa arquitetura: como projetar classes Apex como módulos profundos, como configurar o metadado declarativo McpServerDefinition, a governança de segurança via External Client Apps e as evidências reais de execução testadas na nossa org.
1. O que é um Salesforce Hosted MCP Server?
Pense no Model Context Protocol como o conector USB-C universal da inteligência artificial. Qualquer modelo de linguagem que fale MCP consegue se conectar a um servidor compatível e disparar a pergunta canônica em tempo de execução: “Quais ferramentas você disponibiliza e quais os schemas JSON de entrada e saída?”.
Até recentemente, conectar um cliente MCP externo (como o Claude ou Cursor) ao Salesforce exigia subir uma aplicação Node.js ou Python autohospedada. Esse intermediário recebia a requisição do LLM, autenticava via OAuth clássico, executava SOQLs ou chamadas REST na nuvem da Salesforce e devolvia o payload.
Um trabalho hercúleo. Latência alta, custo de infraestrutura e brechas de manutenção.
Com os Salesforce Hosted MCP Servers, a Salesforce hospeda e gerencia o endpoint MCP nativamente dentro da sua org:


As vantagens arquiteturais são imediatas:
- Grafo de negócios preservado: Uma única invocação de ferramenta navega fluidamente por relacionamentos profundos (
Account -> Opportunity -> OpportunityLineItem) já estruturados no CRM. - Segurança nativa em nível de registro: O servidor executa no contexto do usuário autenticado (
WITH USER_MODE). Se o usuário logado não tiver acesso a uma oportunidade confidencial, o agente de IA simplesmente não enxerga o registro. - Aproveitamento imediato de
@InvocableMethod: Classes que você já construiu para Agentforce ou Flow tornam-se ferramentas operacionais para agentes externos em questão de minutos.
2. A mudança de mentalidade: do dado bruto ao módulo profundo
Aqui está a maior pegadinha cometida por desenvolvedores novatos: criar uma ferramenta genérica chamada executeSOQL e entregá-la para o agente de IA.
Parece tentador. Mas na prática, é um desastre anunciado.
Modelos de linguagem não conhecem a regra de negócio tácita que o seu time levou cinco anos refinando. Se o agente receber uma tabela crua com campos como Tier_Status__c, Custom_Score__c e Has_Overdue_Tasks__c, ele tentará adivinhar o cálculo. Vai gastar milhares de tokens de raciocínio, aumentará a latência para vários segundos e, pior de tudo, alucinará em decisões financeiras sensíveis.
No paradigma Headless 360, a classe Apex deve ser um módulo profundo: ela recebe o mínimo de parâmetros em linguagem natural, faz as consultas relacionais no banco, processa a matemática de negócio no Apex e devolve um parecer estruturado e conclusivo.
Implementação prática: AccountPipelineService.cls
Implementamos e implantamos na nossa org de testes conectada (onlysalesforce_cgc_1) o serviço abaixo. Ele recebe o nome de uma conta, resolve correspondências aproximadas, analisa oportunidades abertas, calcula o valor ponderado de receita e diagnostica o nível de risco:
/*
* Data: 2026-09-24
* Objetivo da Customização: Serviço Apex exposto como ferramenta para agentes de IA via Salesforce Hosted MCP Server (Headless 360)
*/
global with sharing class AccountPipelineService {
global class PipelineRequest {
@InvocableVariable(
required=true
description='O nome da Conta empresarial a ser analisada. Suporta correspondência parcial ou aproximada (ex: Acme para Acme Corp).'
)
global String accountName;
}
global class PipelineResult {
@InvocableVariable(description='Indica se a conta foi localizada com sucesso no CRM.')
global Boolean accountFound;
@InvocableVariable(description='Nome oficial da conta localizada no banco de dados.')
global String resolvedAccountName;
@InvocableVariable(description='Resumo sintético da saúde do pipeline: Forte, Moderado, Em Risco ou Vazio.')
global String pipelineHealthSummary;
@InvocableVariable(description='Valor financeiro total do pipeline em aberto (soma simples das oportunidades).')
global Decimal totalPipelineValue;
@InvocableVariable(description='Valor de receita realista ponderado pela probabilidade percentual de fechamento de cada negócio.')
global Decimal weightedPipelineValue;
@InvocableVariable(description='Quantidade total de negócios abertos no trimestre.')
global Integer openDealsCount;
@InvocableVariable(description='Mensagem explicativa contendo detalhes operacionais ou orientações quando a busca falhar.')
global String message;
}
@InvocableMethod(
label='Obter Analise de Pipeline da Conta'
description='Retorna oportunidades em aberto e inteligência de negócios calculada (níveis de risco, valor ponderado e saúde da carteira) para uma conta. Suporta busca parcial.'
)
global static List<PipelineResult> getAccountPipeline(List<PipelineRequest> requests) {
List<PipelineResult> results = new List<PipelineResult>();
for (PipelineRequest req : requests) {
PipelineResult res = new PipelineResult();
// 1. Resolução inteligente de conta com busca exata e fallback parcial
Account targetAccount = resolveAccount(req.accountName);
if (targetAccount == null) {
res.accountFound = false;
res.message = 'Nenhuma conta localizada com a expressão: ' + req.accountName + '. Solicite esclarecimentos ao usuário sobre a razão social correta.';
results.add(res);
continue;
}
res.accountFound = true;
res.resolvedAccountName = targetAccount.Name;
// 2. Consulta ao grafo de negócios respeitando compartilhamento do usuário
List<Opportunity> openDeals = [
SELECT Id, Name, Amount, StageName, Probability, CloseDate
FROM Opportunity
WHERE AccountId = :targetAccount.Id
AND IsClosed = false
WITH USER_MODE
ORDER BY Amount DESC NULLS LAST
];
// 3. Processamento de regras de inteligência no Apex
res.openDealsCount = openDeals.size();
res.totalPipelineValue = 0;
res.weightedPipelineValue = 0;
Integer highRiskCount = 0;
for (Opportunity opp : openDeals) {
Decimal amount = opp.Amount != null ? opp.Amount : 0;
Decimal prob = opp.Probability != null ? opp.Probability : 0;
res.totalPipelineValue += amount;
res.weightedPipelineValue += (amount * (prob / 100.0));
// Regra de risco: data próxima com baixa probabilidade
Integer daysUntilClose = opp.CloseDate != null ? Date.today().daysBetween(opp.CloseDate) : 999;
if (daysUntilClose <= 30 && prob < 50) {
highRiskCount++;
}
}
// 4. Avaliação qualitativa automatizada
res.pipelineHealthSummary = assessHealth(res.openDealsCount, highRiskCount, res.weightedPipelineValue, res.totalPipelineValue);
res.message = 'Análise concluída com sucesso com base nas oportunidades em aberto.';
results.add(res);
}
return results;
}
private static Account resolveAccount(String nameInput) {
if (String.isBlank(nameInput)) return null;
// Tentativa 1: Busca exata
List<Account> exactMatch = [
SELECT Id, Name
FROM Account
WHERE Name = :nameInput.trim()
WITH USER_MODE
LIMIT 1
];
if (!exactMatch.isEmpty()) return exactMatch[0];
// Tentativa 2: Busca aproximada
String wildCard = '%' + nameInput.trim() + '%';
List<Account> fuzzyMatch = [
SELECT Id, Name
FROM Account
WHERE Name LIKE :wildCard
WITH USER_MODE
LIMIT 1
];
return fuzzyMatch.isEmpty() ? null : fuzzyMatch[0];
}
private static String assessHealth(Integer total, Integer highRisk, Decimal weighted, Decimal totalVal) {
if (total == 0) return 'Vazio (Sem negócios abertos)';
if (Decimal.valueOf(highRisk) / total > 0.4) return 'Em Risco (Alta concentração de negócios com baixa probabilidade)';
if (totalVal > 0 && (weighted / totalVal) >= 0.6) return 'Forte (Alto índice de conversão projetado)';
return 'Moderado (Carteira balanceada com atenção recomendada)';
}
}Observe a assinatura do método: usamos @InvocableMethod e @InvocableVariable. O runtime da Salesforce compila essas anotações e as traduz automaticamente para o JSON Schema que o protocolo MCP entrega aos modelos de linguagem.
3. O arquivo de registro: McpServerDefinition
Depois de implantar a classe Apex, precisamos registrá-la formalmente no catálogo de servidores MCP da organização. Fazemos isso através de um metadado declarativo chamado McpServerDefinition.
Veja o arquivo force-app/main/default/mcpServerDefinitions/PipelineIntelligence.mcpServerDefinition-meta.xml:
<?xml version="1.0" encoding="UTF-8"?>
<McpServerDefinition xmlns="http://soap.sforce.com/2006/04/metadata">
<description>Fornece inteligência preditiva sobre a saúde de vendas e riscos de pipeline no Salesforce CRM.</description>
<masterLabel>Pipeline Intelligence</masterLabel>
<tools>
<apiDefinition>
<apiIdentifier>aa:apex-AccountPipelineService</apiIdentifier>
<apiSource>API_CATALOG</apiSource>
<operation>AccountPipelineService</operation>
</apiDefinition>
<descriptionOverride>Retorna oportunidades abertas, valor ponderado de receita e diagnóstico de risco de fechamento para um determinado nome de cliente. Suporta correspondência parcial de nomes.</descriptionOverride>
<toolName>getAccountPipeline</toolName>
<toolTitle>Obter Analise de Pipeline da Conta</toolTitle>
</tools>
</McpServerDefinition>O segredo está nas descrições
Um desenvolvedor humano lê a documentação em PDF ou testa no Postman. A inteligência artificial, não.
O LLM decide chamar a ferramenta lendo estritamente o texto de descriptionOverride e a tag description de cada @InvocableVariable. Se o texto for ambíguo ou curto demais, o agente simplesmente ignorará a ferramenta. Se for específico e instrutivo, a precisão da chamada chega a quase 100%.
4. Segurança e autenticação: External Client App com PKCE
Nenhum arquiteto sério abre a lógica corporativa da empresa sem segurança de nível militar. O acesso externo aos Hosted MCP Servers é gerenciado pelo External Client App Manager.
Configuração mandatória:
- No Setup do Salesforce, acesse External Client App Manager e crie uma nova aplicação.
- Defina os escopos de OAuth: selecione expressamente
mcp_api(acesso às ferramentas do MCP Server) erefresh_token(sessões contínuas). - Habilite PKCE (Proof Key for Code Exchange) com troca de token via JWT. Nada de senhas fixas ou client secrets em texto puro no cliente de IA.
- Obtenha o endpoint gerado:
- Sandbox / Scratch Org:
https://api.salesforce.com/platform/mcp/v1/sandbox/custom/Pipeline_Intelligence - Produção:
https://api.salesforce.com/platform/mcp/v1/custom/Pipeline_Intelligence
- Sandbox / Scratch Org:
Quando o usuário conecta o Claude ou Cursor usando essa URL e faz login, a sessão herda exatamente os privilégios daquele usuário. Se o profissional for do time de pós-venda sem acesso a preços de oportunidade, o WITH USER_MODE do Apex lança exceção segura de visibilidade e nenhum dado vaza.
5. Evidências de execução real na org conectada
Para demonstrar a eficácia prática deste padrão, implantamos os componentes na nossa org viva (onlysalesforce_cgc_1) e rodamos a suíte de testes e simulações.
Abaixo, a tela do Setup na org comprovando o deploy e a ativação das classes Apex:

Em seguida, executamos a suíte de testes unitários AccountPipelineServiceTest e simulamos a chamada via script anônimo no Developer Console:

O resultado extraído diretamente do log da org fala por si só:
=== Test Results
TEST NAME OUTCOME RUNTIME (MS)
─────────────────────────────────────────────────────────────── ─────── ────────────
AccountPipelineServiceTest.testAccountNotFound Pass 62
AccountPipelineServiceTest.testBlankAccountName Pass 11
AccountPipelineServiceTest.testExactMatchAndPipelineCalculation Pass 66
AccountPipelineServiceTest.testFuzzyMatch Pass 34
=== Apex Code Coverage: 95% (Pass Rate: 100%)
USER_DEBUG|[8]|DEBUG|MCP_RESULT_FOUND: true
USER_DEBUG|[9]|DEBUG|MCP_RESOLVED_NAME: Acme
USER_DEBUG|[10]|DEBUG|MCP_HEALTH_SUMMARY: Em Risco (Alta concentração de negócios com baixa probabilidade)
USER_DEBUG|[11]|DEBUG|MCP_TOTAL_VALUE: 2230000.00
USER_DEBUG|[12]|DEBUG|MCP_WEIGHTED_VALUE: 486000.000
USER_DEBUG|[13]|DEBUG|MCP_MESSAGE: Análise concluída com sucesso com base nas oportunidades em aberto.O serviço resolveu o nome do cliente por aproximação, navegou pela árvore de oportunidades, calculou a soma ponderada de 486 mil reais frente a 2,23 milhões brutos e diagnosticou a carteira como “Em Risco”. Tudo em menos de 80 milissegundos e sem estourar nenhum limite de CPU.
6. Comparativo de paradigmas: UI-first vs. API-first vs. Agent-first
| Dimensão de Engenharia | Padrão UI-first (LWC clássico) | Padrão API-first (REST customizado) | Padrão Agent-first (Hosted MCP) |
|---|---|---|---|
| Consumidor Primário | Usuário humano operando o navegador | Sistemas integradores e microsserviços | Agentes autônomos de IA (Claude, Cursor, GPT) |
| Protocolo de Comunicação | Eventos DOM e Lightning Data Service | Contratos rígidos REST/JSON | Model Context Protocol (JSON-RPC padronizado) |
| Descoberta de Funções | Navegação visual por menus e abas | Leitura manual de documentação Swagger | Descoberta dinâmica em runtime via tools/list |
| Natureza da Resposta | Renderização de cards, tabelas e botões | Listas cruas de dados relacionais | Diagnósticos de negócio e conclusões calculadas |
| Gargalo Operacional | Fricção de cliques e lentidão humana | Custo de manutenção de código cliente | Zero fricção: o agente decide quando e como agir |
Lição aprendida para o arquiteto moderno
A revolução dos agentes de inteligência artificial não significa que o Apex morreu. Muito pelo contrário.
O código Apex agora ganha o seu papel mais nobre: deixar de ser mero alimentador de formulários em tela para se tornar o motor transacional soberano que impede que agentes de IA tomem decisões cegas no mundo real.
Se a sua empresa ainda está desenhando estratégias de Salesforce pensando apenas em layouts de página e botões de tela, você está construindo sistemas para o passado. Exponha sua inteligência em módulos profundos via Hosted MCP Servers e coloque o seu CRM para conversar com os cérebros digitais que já estão moldando a nova economia de software.
