Model Context Protocol (MCP)

O Model Context Protocol (MCP) é um padrão aberto que padroniza a forma como aplicações de IA se comunicam com fontes de dados e ferramentas externas. Enquanto o Function Calling permite ao LLM invocar funções locais da aplicação, o MCP vai além: ele define um protocolo de comunicação que permite ao LLM interagir com servidores remotos de forma segura, bidirecional e agnóstica de linguagem.

Criado pela Anthropic e adotado amplamente pela comunidade, o MCP funciona como um “conector universal” entre agentes de IA e o ecossistema de ferramentas e dados ao redor. Um servidor MCP pode ser escrito em qualquer linguagem (Python, TypeScript, Java) e ser consumido por qualquer cliente MCP compatível.

Arquitetura MCP

A arquitetura do MCP é composta por dois papéis principais: o MCP Server e o MCP Client.

Arquitetura MCP: AI Agent orquestrando múltiplas ferramentas

A imagem acima ilustra um exemplo concreto de agente MCP: a partir de um prompt do usuário, o AI Agent orquestra três ferramentas em sequência:

  1. City Extractor Tool: extrai o nome da cidade mencionada no prompt (executa localmente, usando o próprio LLM como ferramenta de extração).
  2. Geocoding Tool: converte o nome da cidade em coordenadas geográficas (latitude/longitude), consultando uma API externa.
  3. Weather Forecast Service: usa as coordenadas para buscar a previsão do tempo em uma API meteorológica remota.

O resultado de cada tool alimenta a próxima etapa, e o agente combina todas as informações para entregar a resposta final ao usuário. Esse encadeamento de ferramentas é exatamente o que o MCP padroniza: uma forma comum de expor e invocar ferramentas, locais ou remotas, de qualquer aplicação de IA.

┌─────────────────────────────────────────────────────────┐
│                    Aplicação (MCP Client)                │
│                                                         │
│   AI Service ──── @McpToolBox ──── MCP Client           │
│                                        │                │
└────────────────────────────────────────┼────────────────┘
                                         │ HTTP/SSE
                                         ▼
                             ┌───────────────────────┐
                             │   MCP Server (remoto)  │
                             │                       │
                             │  @Tool getForecast()  │
                             │  @Tool getStocks()    │
                             │  ...                  │
                             └───────────────────────┘

O fluxo de comunicação segue os mesmos princípios do Function Calling local, mas com a execução das ferramentas ocorrendo em um processo separado, potencialmente em outra máquina:

  1. O LLM recebe a lista de tools disponíveis no servidor MCP (via @McpToolBox).
  2. O LLM decide invocar uma tool e retorna uma tool call request.
  3. O MCP Client (na aplicação) transmite a requisição ao MCP Server via HTTP/SSE.
  4. O MCP Server executa a tool e retorna o resultado.
  5. O MCP Client repassa o resultado ao LLM.
  6. O LLM formula a resposta final ao usuário.

Criando um MCP Server com Quarkus

Dependências

Para criar um servidor MCP com Quarkus, adicione a extensão quarkus-mcp-server-sse e o REST Client para consumir APIs externas:

quarkus create app dev.langchain4j.quarkus.workshop:mcp-server:1.0-SNAPSHOT \
  -x quarkus-mcp-server-sse \
  -x quarkus-rest-client-jackson

Ou adicione as dependências manualmente ao pom.xml:

<dependency>
    <groupId>io.quarkiverse.mcp</groupId>
    <artifactId>quarkus-mcp-server-sse</artifactId>
</dependency>
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-rest-client-jackson</artifactId>
</dependency>

Definindo um REST Client

O servidor MCP pode chamar APIs externas para enriquecer as respostas. No exemplo do workshop, é criado um cliente REST que consulta previsões meteorológicas:

@Path("/v1/forecast")
@RegisterRestClient(configKey = "weatherclient")
public interface WeatherClient {

    @GET
    String getForecast(
            @RestQuery double latitude,
            @RestQuery double longitude,
            @RestQuery int forecastDays,
            @RestQuery String hourly
    );
}

Definindo Tools no MCP Server

Assim como no Function Calling local, as tools do MCP Server são métodos Java anotados com @Tool. A diferença é que agora essas ferramentas ficam em um processo separado e são expostas remotamente via protocolo MCP:

public class Weather {

    @RestClient
    WeatherClient weatherClient;

    @Tool(description = "Get weather forecast for a location.")
    String getForecast(
            @ToolArg(description = "Latitude of the location") double latitude,
            @ToolArg(description = "Longitude of the location") double longitude) {

        return weatherClient.getForecast(
                latitude,
                longitude,
                16,
                "temperature_2m,snowfall,rain,precipitation,precipitation_probability");
    }
}

Note o uso de @ToolArg (em vez de apenas nomear o parâmetro) para fornecer ao LLM uma descrição semântica de cada argumento.

Configurando o MCP Server

No application.properties do servidor MCP:

# Porta diferente da aplicação cliente
quarkus.http.port=8081

# Identificação e logs do servidor MCP
quarkus.mcp.server.server-info.name=Weather Service
quarkus.mcp.server.traffic-logging.enabled=true
quarkus.mcp.server.traffic-logging.text-limit=100

# REST Client para a API meteorológica
quarkus.rest-client.logging.scope=request-response
quarkus.rest-client.follow-redirects=true
quarkus.rest-client.logging.body-limit=50
quarkus.rest-client."weatherclient".uri=https://api.open-meteo.com/

Configurando o MCP Client (aplicação principal)

Dependência

Na aplicação que consome o MCP Server, adicione a dependência:

<dependency>
    <groupId>io.quarkiverse.langchain4j</groupId>
    <artifactId>quarkus-langchain4j-mcp</artifactId>
</dependency>

Ou via CLI:

./mvnw quarkus:add-extension -Dextensions="quarkus-langchain4j-mcp"

Configuração do transporte

No application.properties da aplicação cliente, aponte para o servidor MCP:

quarkus.langchain4j.mcp.weather.transport-type=http
quarkus.langchain4j.mcp.weather.url=http://localhost:8081/mcp/sse/

O nome weather é o identificador do servidor MCP. Ele será referenciado na anotação @McpToolBox.

Configurando o AI Service com @McpToolBox

Para expor as tools do servidor MCP ao LLM, use a anotação @McpToolBox no AI Service:

@SessionScoped
@RegisterAiService
public interface CustomerSupportAgent {

    @SystemMessage("""
            You are a customer support agent of a car rental company 'Miles of Smiles'.
            You are friendly, polite and concise.
            If the question is unrelated to car rental, you should politely redirect
            the customer to the right department.

            When calling tools or functions, strictly use JSON objects,
            do not wrap in quotes or use plain strings.

            When asked to provide details about a reservation,
            provide weather details and gently try to upsell the customer
            based on this info.

            Today is {current_date}.
            """)
    @ToolBox(BookingRepository.class)
    @McpToolBox("weather")
    String chat(String userMessage);
}

Dois pontos importantes:

  • @McpToolBox("weather"): referencia o servidor MCP pelo nome configurado em application.properties. O Quarkus LangChain4j descobre automaticamente as tools disponíveis no servidor e as inclui nas requisições ao LLM.
  • @ToolBox e @McpToolBox podem coexistir: é possível combinar tools locais (Function Calling) com tools remotas (MCP) no mesmo AI Service.

Function Calling Local vs. MCP

Ambas as abordagens permitem ao LLM executar ações além de responder perguntas. A escolha depende do contexto:

Aspecto Function Calling (@ToolBox) MCP (@McpToolBox)
Localização Execução local, dentro da aplicação Execução remota, em servidor separado
Reusabilidade Limitada à aplicação Alta: qualquer cliente MCP pode usar
Linguagem Java Qualquer linguagem
Transporte In-process HTTP com SSE
Complexidade Baixa Moderada
Ideal para Lógica de negócio própria APIs externas, ferramentas compartilhadas

As duas técnicas são complementares e podem ser combinadas no mesmo AI Service.

Referência

Quarkus LangChain4j Workshop, Step 08

Rodrigo Prestes Machado
CC BY 4.0 DEED