MCP (Model Context Protocol) se torna padrão de conexão de ferramentas
1. Visão Geral
Os grandes modelos de linguagem (LLMs) são realmente úteis apenas quando conseguem ler dados reais e chamar sistemas reais: consultar pedidos, ler tickets, executar queries. Antes, cada aplicação de IA escrevia sua própria forma de integração para cada ferramenta. Model Context Protocol (MCP) foi criado para padronizar essa parte de conexão.
Este artigo explica o que é MCP e por que está recebendo atenção. Depois você vai escrever um pequeno MCP server em Spring Boot, configurar um client para chamá-lo, e aprender quando não deverias usar MCP.
2. O que é MCP?
MCP é um protocolo aberto. Ele define como uma aplicação de IA descobre e chama capacidades externas: ferramentas, dados e prompts de modelo. Você pode pensar no MCP como a “porta USB” da IA. Qualquer dispositivo que siga o padrão funciona quando conectado a qualquer host que suporte o padrão.
2.1. Três papéis principais
- Host: aplicação com a qual o usuário interage, por exemplo um assistente de IA no desktop, uma IDE ou um chatbot interno.
- Client: componente dentro do host. Cada client mantém uma conexão um-para-um com um servidor.
- Server: programa que fornece capacidades para a IA, por exemplo um servidor que lê banco de dados de pedidos ou um servidor que acessa o sistema de arquivos.
2.2. Três tipos de “primitivos” no lado do servidor
- Tools: funções que o modelo pode decidir chamar, como
findOrderoucancelOrder. - Resources: dados somente leitura, como conteúdo de arquivo ou registros de configuração, inseridos no context.
- Prompts: templates de prompt pré-construídos que o usuário pode escolher para usar.
2.3. Protocolo subjacente
MCP usa JSON-RPC 2.0. Os dois tipos de transporte mais comuns são: stdio, quando o host inicia o servidor como um processo filho, e HTTP, quando o servidor roda remotamente. Uma chamada de ferramenta se parece com isto:
{
"jsonrpc": "2.0",
"id": 7,
"method": "tools/call",
"params": {
"name": "findOrder",
"arguments": { "orderId": "ORD-1001" }
}
}
O fluxo de operação básico consiste em três etapas:
- O client envia
initializepara que os dois lados troquem versão do protocolo e capacidades suportadas. - O client chama
tools/listpara obter a lista de ferramentas, junto com descrição e JSON Schema dos parâmetros. - Quando o modelo decide usar uma ferramenta, o client envia
tools/callconforme o exemplo acima e retorna o resultado ao modelo.
Ponto importante: o modelo não chama o servidor diretamente. O host fica no meio, então pode pedir confirmação do usuário antes de executar uma ferramenta sensível.
3. Por que MCP está recebendo atenção?
3.1. O problema N × M
Suponha que haja N aplicações de IA e M sistemas para conectar. Sem um padrão comum, você precisa escrever N × M integrações. Com um protocolo comum, cada aplicação só precisa suportar MCP uma vez, e cada sistema só precisa de um MCP server. O problema reduz para N + M.
3.2. Separação de responsabilidades
O time que possui o sistema de pedidos escreve e opera o MCP server dele. O time do chatbot só precisa apontar para esse servidor. A lógica de negócio, controle de acesso e logs de auditoria ficam no lugar certo, sem serem duplicados em cada prompt ou aplicação.
3.3. Não fica preso a um fornecedor de modelo
A chamada de função de cada fornecedor de LLM tem seu próprio formato. MCP fica em uma camada acima desse formato. O servidor que você escreve hoje ainda funciona quando você muda de modelo ou de host.
3.4. O ecossistema está crescendo
Cada vez mais assistentes de IA, IDEs e frameworks suportam MCP. Há SDKs para muitas linguagens, incluindo um SDK oficial para Java e integração no Spring AI. É por isso que muitas pessoas veem MCP como candidato promissor para um padrão de conexão de ferramentas. Mesmo assim, o protocolo ainda está em desenvolvimento, então você precisa acompanhar a spec ao fazer deployments de longo prazo.
4. Escrevendo um MCP server com Spring Boot
Você vai construir um servidor que fornece duas ferramentas para consultar e cancelar pedidos, rodando via stdio.
4.1. Dependência
Spring AI fornece um starter para MCP server. Importe o BOM do Spring AI e use a versão mais recente compatível com sua versão Spring Boot 3.x:
<properties>
<java.version>21</java.version>
<spring-ai.version><!-- versão atual do Spring AI --></spring-ai.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring-ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server</artifactId>
</dependency>
</dependencies>
O starter spring-ai-starter-mcp-server suporta transporte stdio. Se você quiser rodar o servidor via HTTP, Spring AI tem starters separados para Web MVC e WebFlux.
Nota: O nome do artifact do Spring AI mudou entre versions milestone. Verifique a documentação da versão que você escolher.
4.2. Domain e ferramentas
public record Order(String id, String customerName, double total, String status) {}
@Service
public class OrderTools {
private final Map<String, Order> orders = new ConcurrentHashMap<>(Map.of(
"ORD-1001", new Order("ORD-1001", "Nguyen Van An", 350_000, "SHIPPING"),
"ORD-1002", new Order("ORD-1002", "Tran Thi Binh", 120_000, "PENDING")
));
@Tool(description = "Buscar pedido por código, retorna cliente, valor total e status")
public Order findOrder(@ToolParam(description = "Código do pedido, ex: ORD-1001") String orderId) {
Order order = orders.get(orderId);
if (order == null) {
throw new IllegalArgumentException("Pedido não encontrado: " + orderId);
}
return order;
}
@Tool(description = "Cancelar pedido. Só é possível cancelar pedidos com status PENDING")
public String cancelOrder(@ToolParam(description = "Código do pedido a cancelar") String orderId) {
Order order = findOrder(orderId);
if (!"PENDING".equals(order.status())) {
return "Não é possível cancelar: pedido está com status " + order.status();
}
orders.put(orderId, new Order(order.id(), order.customerName(), order.total(), "CANCELLED"));
return "Pedido " + orderId + " cancelado";
}
}
Duas anotações têm papéis principais:
@Tool(pacoteorg.springframework.ai.tool.annotation) marca o método como ferramenta. A partedescriptioné exatamente o que o modelo lê para decidir se vai chamar a ferramenta ou não. Quanto mais clara a descrição, melhor o modelo escolhe.@ToolParamdescreve cada parâmetro. Spring AI gera JSON Schema a partir do tipo de parâmetro e dessa descrição.
Note que cancelOrder retorna uma mensagem em vez de lançar uma exceção quando há violação de regra de negócio. O modelo lê essa mensagem e explica naturalmente ao usuário.
4.3. Registrando ferramentas com MCP server
@SpringBootApplication
public class OrderMcpServerApplication {
public static void main(String[] args) {
SpringApplication.run(OrderMcpServerApplication.class, args);
}
@Bean
ToolCallbackProvider orderToolProvider(OrderTools orderTools) {
return MethodToolCallbackProvider.builder()
.toolObjects(orderTools)
.build();
}
}
MethodToolCallbackProvider escaneia métodos com @Tool em orderTools. A auto-configuração do MCP server encontrará todo bean ToolCallbackProvider e os publicará via tools/list.
4.4. Configuração para stdio
spring.ai.mcp.server.name=order-mcp-server
spring.ai.mcp.server.version=0.0.1
spring.ai.mcp.server.stdio=true
spring.main.web-application-type=none
spring.main.banner-mode=off
logging.pattern.console=
logging.file.name=./logs/order-mcp-server.log
Com stdio, stdout é o canal de transmissão JSON-RPC. Qualquer outra coisa impressa em stdout vai quebrar o protocolo, inclusive banner e logs. Por isso a configuração acima desativa o banner, desativa logs no console e envia os logs para arquivo.
Nota: Este é o erro mais comum ao começar a trabalhar com MCP server via stdio. Até uma linha
System.out.printlnpara debug pode fazer o client reportar erro de parsing ou desconectar. Use um logger que escreva em arquivo.
Build para arquivo jar:
./mvnw clean package -DskipTests
5. Conectando do lado cliente
Muitos hosts configuram o servidor via um arquivo JSON com a chave mcpServers. O nome e localização do arquivo dependem de cada host:
{
"mcpServers": {
"orders": {
"command": "java",
"args": ["-jar", "/opt/mcp/order-mcp-server.jar"]
}
}
}
Ao inicializar, o host executa o comando java -jar ... como um processo filho, envia initialize e depois tools/list. Você pergunta: “Ainda é possível cancelar o pedido ORD-1002? Se for, cancela para mim.” O modelo vai chamar findOrder e depois cancelOrder. O resultado do segundo chamado fica assim:
{"content":[{"type":"text","text":"Pedido ORD-1002 cancelado"}],"isError":false}
Normalmente o host vai mostrar uma caixa de diálogo pedindo permissão antes de executar a ferramenta. Você deve manter esse comportamento para ferramentas com efeitos colaterais como cancelOrder.
Se você quiser que sua aplicação Spring atue como client, Spring AI também tem um starter MCP client. Esse starter transforma ferramentas de servidores externos em ferramentas que podem ser usadas com ChatClient.
6. Testando o comportamento das ferramentas
Ferramentas são apenas métodos Java normais, então você pode testá-las sem inicializar MCP:
class OrderToolsTest {
private final OrderTools tools = new OrderTools();
@Test
void shouldCancelPendingOrder() {
String result = tools.cancelOrder("ORD-1002");
assertThat(result).isEqualTo("Pedido ORD-1002 cancelado");
assertThat(tools.findOrder("ORD-1002").status()).isEqualTo("CANCELLED");
}
@Test
void shouldRefuseToCancelShippingOrder() {
assertThat(tools.cancelOrder("ORD-1001"))
.contains("Não é possível cancelar")
.contains("SHIPPING");
}
@Test
void shouldFailWhenOrderNotFound() {
assertThatThrownBy(() -> tools.findOrder("ORD-9999"))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("ORD-9999");
}
}
Os três testes cobrem o fluxo bem-sucedido, regras de negócio e o caso de pedido não encontrado. O SDK já cuida da parte do protocolo. O mais importante é garantir que a lógica de negócio retorne resultados corretos e mensagens claras para o modelo.
Para testar end-to-end, você pode usar ferramentas de inspetor para MCP. Elas permitem listar ferramentas e chamá-las manualmente.
7. Aplicação prática: o que considerar
- Projete ferramentas de acordo com a lógica de negócio, não com tabelas.
findOrderé melhor do que uma ferramenta genéricaexecuteSql. Ferramentas estreitas são mais fáceis de controlar permissões e ajudam o modelo a fazer a escolha certa. - Privilégios mínimos. O servidor deve usar uma conta que tenha apenas as permissões necessárias. Separe ferramentas de leitura e escrita, e considere ativar ferramentas de escrita apenas em alguns ambientes.
- Tenha cuidado com prompt injection. Dados que as ferramentas retornam, como notas inseridas por clientes, podem conter instruções para controlar o modelo. Não deixe que resultados de uma ferramenta automaticamente acionem ações perigosas sem confirmação do usuário.
- Confie apenas em servidores confiáveis. Um MCP server de terceiros rodando via stdio é um processo na sua máquina, com suas permissões. As descrições das ferramentas também podem conter conteúdo malicioso. Leia o código-fonte ou use apenas de fontes que você confia.
- Autenticação para servidores remotos. Ao rodar via HTTP, coloque o servidor atrás de um mecanismo de autenticação apropriado e registre logs de auditoria para cada chamada de ferramenta.
- Mantenha uma quantidade razoável de ferramentas. Cada ferramenta consome espaço de contexto para sua descrição. Muitas ferramentas fazem o modelo escolher a errada mais facilmente.
8. Quando NÃO usar MCP
- Aplicação pequena, só um modelo, poucas funções. A chamada de função direta do framework, como
@Toolusado diretamente comChatClient, é mais simples. Você não precisa de um processo extra e uma camada de protocolo. - Fluxo de processamento fixo, sem necessidade do modelo decidir. Se a etapa 1 sempre chama API A e depois a etapa 2 sempre chama API B, escreva código normal. Não delegue ao LLM tarefas que um simples
iffaz melhor. - Requisitos de latência extremamente baixa ou alta determinabilidade. Cada ciclo modelo → client → servidor adiciona latência. Os resultados do modelo também não são completamente determinísticos.
- Operações não reversíveis sem revisão humana. Transferências de dinheiro ou exclusão em massa não devem ser expostas como ferramentas automáticas. Se absolutamente necessário, sempre inclua uma etapa de confirmação.
- Você precisa de uma API para outros sistemas chamarem. MCP foi criado para servir a IA. Entre serviços, REST, gRPC ou mensageria ainda são a escolha certa.
9. Conclusão
MCP resolve um problema muito real: conectar IA com ferramentas e dados de forma padronizada, em vez de cada aplicação escrever sua própria forma. Graças ao modelo host–client–server, três primitivos tools/resources/prompts e a base JSON-RPC, um servidor que você escreve pode ser reutilizado em muitos hosts diferentes.
Com Spring AI, escrever um MCP server requer apenas algumas anotações @Tool, um bean ToolCallbackProvider e configuração correta para stdio. A parte difícil está em outro lugar: projetar ferramentas estreitas e claras, aplicar permissões rígidas, estar atento a prompt injection. Você também precisa ter a clareza de reconhecer casos em que código normal ainda é a solução melhor.