Cliente MCP de LangChain4j: conecta Java a un servidor MCP
Introducción
Para conectar una aplicación Java a un servidor Model Context Protocol (MCP) con el cliente MCP de LangChain4j, añades el módulo langchain4j-mcp, creas un transporte (STDIO para un servidor que se ejecuta como subproceso local, Streamable HTTP para un servidor al que accedes por la red) y lo envuelves en un DefaultMcpClient.
Después pasas el cliente a un McpToolProvider, y cualquier AI service de LangChain4j puede llamar a las herramientas del servidor.
MCP proporciona una forma estandarizada para que los modelos de inteligencia artificial (IA) interactúen con herramientas y sistemas externos. Echa un vistazo a mi introducción a MCP si el protocolo es nuevo para ti.
En este artículo, te mostraré cómo conectar tus aplicaciones Java a un servidor MCP usando LangChain4j, lo que permitirá que tus agentes de IA realicen acciones del mundo real, como gestionar Pods de Kubernetes.
Cubriré tanto el transporte STDIO como Streamable HTTP, qué versión del protocolo usar con cada uno, cómo limitar las herramientas que puede usar el modelo y cómo uso LangChain4j para testear implementaciones de servidores MCP.
He probado cada paso en octubre de 2026 con LangChain4j 1.22.0 (langchain4j-mcp 1.22.0-beta32), Temurin JDK 25, Kubernetes MCP Server v0.0.67 y un modelo local pequeño (Qwen3 4B) ejecutándose en Ollama, así que puedes seguirlo sin una API key.
¿Qué versión de LangChain4j necesitas?
LangChain4j publicó su primer cliente MCP en la versión 1.0.0-alpha1 (diciembre de 2024), un mes después de que Anthropic presentara el protocolo, y escribí la primera versión de este artículo en marzo de 2025 con la 1.0.0-beta1. Desde entonces, el cliente MCP ha cambiado lo suficiente como para que el código de tutoriales antiguos no compile con una versión actual:
| Versión de LangChain4j | Cambios en el cliente MCP |
|---|---|
| 1.0.0-alpha1 (dic 2024) | Primer cliente MCP, con los transportes STDIO y SSE (HttpMcpTransport) |
| 1.4.0 (ago 2025) | StreamableHttpMcpTransport |
| 1.6.0 (sep 2025) | executeTool() devuelve ToolExecutionResult en lugar de String |
| 1.19.0 (ago 2026) | Soporte de MCP 2026-07-28 y detección del protocolo; se elimina HttpMcpTransport (SSE) |
| 1.22.0 (oct 2026) | Última versión a fecha de octubre de 2026, la que uso en este artículo |
Si tu build falla con cannot find symbol: class HttpMcpTransport después de actualizar, sustitúyelo por StreamableHttpMcpTransport y apúntalo al endpoint Streamable HTTP del servidor, como te muestro más adelante.
Además, desde la 1.6.0, McpClient.executeTool() devuelve un ToolExecutionResult en lugar de un String; llama a resultText() para obtener el texto.
Configuración de clientes MCP con LangChain4j
LangChain4j proporciona una API de cliente MCP flexible para conectarse a servidores MCP a través de diferentes mecanismos de transporte. El cliente se sitúa entre tu aplicación Java y el servidor MCP: arranca el servidor o se conecta a él, lista sus herramientas y las invoca.
Añadir la dependencia MCP de LangChain4j
LangChain4j necesita Java 17 o posterior.
El cliente MCP vive en su propio módulo, langchain4j-mcp, que a fecha de octubre de 2026 todavía se publica con el sufijo -beta (1.22.0-beta32 es la versión que corresponde a LangChain4j 1.22.0).
El BOM de LangChain4j elige la versión correspondiente por ti, así que con Maven solo tienes que importarlo y declarar los módulos:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-bom</artifactId>
<version>1.22.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-mcp</artifactId>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-ollama</artifactId>
</dependency>
</dependencies>Con Gradle, el equivalente es implementation(platform("dev.langchain4j:langchain4j-bom:1.22.0")) más los dos módulos sin versión.
langchain4j-ollama es el proveedor de modelos que uso más adelante en este artículo; cámbialo por el proveedor que prefieras.
La especificación MCP define dos transportes estándar: Entrada/Salida Estándar (STDIO) y Streamable HTTP. Veamos cómo configurar cada uno de ellos.
Configuración de un cliente de transporte STDIO
El método de transporte STDIO lanza un servidor MCP como un subproceso y se comunica con él a través de flujos de entrada/salida estándar. Este método es el más adecuado para ejecuciones locales, lo que resulta práctico para agentes que realizan tareas en la misma máquina donde se está ejecutando el servidor. Gestionar recursos locales, ejecutar comandos de shell o interactuar con servicios locales son casos de uso habituales del transporte STDIO.
El siguiente fragmento de código muestra cómo configurar un cliente de transporte STDIO en LangChain4j:
import dev.langchain4j.mcp.client.DefaultMcpClient;
import dev.langchain4j.mcp.client.McpClient;
import dev.langchain4j.mcp.client.transport.stdio.StdioMcpTransport;
public final class LangChainMcpClient {
static McpClient initStdioClient(String... command) {
return DefaultMcpClient.builder()
// Optional client name to identify with the server, defaults to "langchain4j"
.clientName("blog.marcnuri.com")
// Optional timeout for each individual tool execution, defaults to 60 seconds
.toolExecutionTimeout(Duration.ofSeconds(30))
.transport(StdioMcpTransport.builder()
// The command that starts the MCP server
.command(List.of(command))
// Optional, log the MCP messages (DEBUG level of the "MCP" logger)
.logEvents(true)
.build())
.build();
}
}Estos son los componentes clave de la configuración del cliente de transporte STDIO:
clientName: Un parámetro opcional que identifica al cliente ante el servidor. Si no se especifica, el nombre del cliente por defecto eslangchain4j.toolExecutionTimeout: Un parámetro opcional para establecer el tiempo de espera de cada ejecución de herramienta. Si no se especifica, el tiempo de espera por defecto es de 60 segundos.StdioMcpTransport.command: El comando para ejecutar el servidor MCP. Debe ser una lista de Strings que representan el comando y sus argumentos, por ejemploinitStdioClient("npx", "-y", "kubernetes-mcp-server@latest"). En Windows, usanpx.cmden lugar denpx.StdioMcpTransport.logEvents: Un parámetro opcional para habilitar la traza de los mensajes MCP. LangChain4j los registra con nivel DEBUG en un logger llamadoMCP, así que también tienes que habilitar ese logger en tu configuración de logging.
El subproceso hereda todo el entorno de tu aplicación, así que Kubernetes MCP Server encuentra tu KUBECONFIG y tus variables de proxy sin ninguna configuración adicional.
También recibe cualquier API key o token que haya en ese entorno, así que ejecuta solo servidores en los que confíes.
Si el servidor necesita una variable que tu aplicación no tiene, añádela con el método environment(Map<String, String>) del transporte.
¿Qué versión del protocolo MCP usa el cliente?
Desde LangChain4j 1.19.0, el cliente detecta la versión del protocolo al conectarse: envía la petición server/discover de la revisión 2026-07-28, que sustituyó el handshake initialize por metadatos que viajan con cada petición, y vuelve al handshake clásico initialize (2025-11-25) si el servidor responde con un error.
protocolVersion("2026-07-28") o protocolVersion("2025-11-25") en el builder del cliente omite la detección y fuerza una versión.
Con STDIO, la detección por defecto funciona: Kubernetes MCP Server v0.0.67 soporta la revisión 2026-07-28, y es la que negoció el cliente en mis pruebas. Con Streamable HTTP, depende del servidor, como te explico en la siguiente sección.
Configuración de un cliente de transporte Streamable HTTP
El método de transporte Streamable HTTP establece una conexión con el servidor MCP a través de HTTP utilizando un único endpoint para la mensajería bidireccional. Este método es adecuado para ejecuciones remotas, donde el servidor se ejecuta en una máquina diferente o en un entorno en la nube. Interactuar con servicios web, gestionar recursos en la nube (como Kubernetes) o ejecutar tareas de larga duración son casos de uso habituales del transporte Streamable HTTP.
Nota
Antes de la versión 2025-03-26 del protocolo MCP, el transporte SSE (Server-Sent Events) se utilizaba para conexiones remotas.
SSE está ahora obsoleto en favor de Streamable HTTP, y LangChain4j eliminó su transporte SSE (HttpMcpTransport) en la versión 1.19.0.
Para probarlo en local, arranca Kubernetes MCP Server en modo HTTP en otro terminal:
npx -y kubernetes-mcp-server@latest --port 8080 --bind-address 127.0.0.1Sin --bind-address, el servidor escucha en todas las interfaces de red (0.0.0.0) y, por defecto, no autentica a sus clientes, así que cualquiera que pueda llegar al puerto puede utilizar tu clúster con las credenciales de tu kubeconfig.
El siguiente fragmento de código muestra cómo configurar un cliente de transporte Streamable HTTP en LangChain4j:
import dev.langchain4j.mcp.client.DefaultMcpClient;
import dev.langchain4j.mcp.client.McpClient;
import dev.langchain4j.mcp.client.transport.http.StreamableHttpMcpTransport;
public final class LangChainMcpClient {
static McpClient initHttpClient(String url) {
return DefaultMcpClient.builder()
.clientName("blog.marcnuri.com")
.toolExecutionTimeout(Duration.ofSeconds(30))
// Skip protocol detection: over HTTP, the Kubernetes MCP Server speaks 2026-07-28 only with --stateless
.protocolVersion("2025-11-25")
.transport(StreamableHttpMcpTransport.builder()
// The URL of the MCP server's endpoint
.url(url)
// Optional, log the MCP requests and responses (INFO level of the "MCP" logger)
.logRequests(true)
.logResponses(true)
.build())
.build();
}
}Estos son los componentes clave de la configuración del cliente de transporte Streamable HTTP:
protocolVersion: Fuerza el protocolo 2025-11-25 y omite la detección. Te explico por qué más abajo.StreamableHttpMcpTransport.url: La URL del endpoint del servidor MCP,http://127.0.0.1:8080/mcppara el servidor que acabamos de arrancar.StreamableHttpMcpTransport.logRequestsylogResponses: Parámetros opcionales para registrar los mensajes de petición y respuesta MCP.- El builder también acepta
customHeaders(Map<String, String>), por ejemplo para enviar una cabeceraAuthorizationa un servidor remoto, que además debería usar HTTPS.
Para usarlo, pasa initHttpClient("http://127.0.0.1:8080/mcp") al método assistant de más abajo en lugar del cliente STDIO.
Advertencia
Con HTTP, Kubernetes MCP Server solo soporta la revisión 2026-07-28 cuando se ejecuta con --stateless; por defecto, responde a la petición server/discover del cliente con las versiones anteriores que soporta.
LangChain4j 1.22.0 no comprueba esa lista: cambia igualmente al protocolo 2026-07-28, y todas las peticiones siguientes fallan con HttpException: Unexpected status code: 400.
Establecer protocolVersion("2025-11-25") evita el problema con cualquier servidor; si ejecutas tú el servidor, arrancarlo con --stateless también funciona, a costa de perder sus notificaciones de cambios en las herramientas y los prompts.
Ejemplo: un agente de IA en Java que usa Kubernetes MCP Server
Una vez que tengas configurado tu cliente MCP, puedes integrarlo con los AI services de LangChain4j para crear un asistente que pueda interactuar con el mundo real.
Los ejemplos utilizan un modelo local a través de Ollama. Instala Ollama y descarga un modelo pequeño que soporte tool calling (unos 2,5 GB):
ollama pull qwen3:4b-instructKubernetes MCP Server también necesita un clúster con el que hablar.
Utiliza tu fichero kubeconfig por defecto, así que cualquier clúster sirve; yo utilicé un clúster local de kind con un Deployment nginx de dos réplicas.
Los ejemplos arrancan el servidor con npx, así que también necesitas Node.js; npx descarga el binario del servidor para tu plataforma.
Aquí te muestro cómo crear un asistente muy sencillo que puede gestionar un clúster de Kubernetes usando Kubernetes MCP Server:
import dev.langchain4j.mcp.McpToolProvider;
import dev.langchain4j.mcp.client.McpClient;
import dev.langchain4j.model.ollama.OllamaChatModel;
import dev.langchain4j.service.AiServices;
import dev.langchain4j.service.tool.ToolArgumentsErrorHandler;
import dev.langchain4j.service.tool.ToolExecutionErrorHandler;
public final class LangChainMcpClient {
interface Assistant {
String chat(String userMessage);
}
static Assistant assistant(McpClient client) {
return AiServices.builder(Assistant.class)
.chatModel(OllamaChatModel.builder()
.baseUrl("http://localhost:11434")
.modelName("qwen3:4b-instruct")
.timeout(Duration.ofMinutes(5))
.build())
.toolProvider(McpToolProvider.builder().mcpClients(client).build())
.toolArgumentsErrorHandler(ToolArgumentsErrorHandler.sendExceptionMessageToLlm())
.toolExecutionErrorHandler(ToolExecutionErrorHandler.failInvocationUnlessVisibleToLlm())
.build();
}
public static void main(String[] args) throws Exception {
// On Windows, use "npx.cmd"
try (var client = initStdioClient("npx", "-y", "kubernetes-mcp-server@latest")) {
final var assistant = assistant(client);
System.out.println(assistant.chat("Run a Pod with the image marcnuri/chuck-norris and expose port 8080"));
System.out.println(assistant.chat("List all pods in my cluster and output their name and namespace as a Markdown table"));
}
}
}En este ejemplo, creamos un asistente muy sencillo que conecta las herramientas de Kubernetes MCP Server con el modelo Qwen3 4B ejecutándose en Ollama.
Estos son los componentes clave del ejemplo de integración del asistente:
Assistant:
La interfaz más simple para un asistente que proporciona un métodochatpara interactuar con el modelo de IA. Los AI services de LangChain4j utilizan esta interfaz para crear automáticamente la implementación del asistente.OllamaChatModel:
Un modelo de chat que envía las peticiones a un servidor local de Ollama. Podríamos usar cualquier otro modelo e implementación deChatModelproporcionados por LangChain4j, siempre que el modelo soporte tool calling.baseUrl: La URL del servidor de Ollama (Ollama escucha enhttp://localhost:11434por defecto); obligatorio.modelName: El nombre del modelo a usar.timeout: Los modelos pequeños pueden tardar en responder en un portátil, así que lo he subido desde los 60 segundos por defecto.
McpToolProvider:
Un proveedor de herramientas que utiliza el cliente MCP para ejecutar herramientas en el servidor MCP. El métodomcpClientsacepta uno o más clientes MCP para la ejecución de herramientas.toolArgumentsErrorHandlerytoolExecutionErrorHandler:
En LangChain4j 1.22.0, un AI service con herramientas registra un aviso a menos que elijas estos handlers de forma explícita, porque está previsto que cambien sus valores por defecto. Estos dos son los recomendados: el modelo ve sus propios errores de argumentos y los errores que reporta el servidor MCP, y cualquier otra excepción hace fallar la llamada en lugar de llegar al modelo.
Consejo
Para usar un modelo alojado, solo tienes que cambiar el chatModel.
Por ejemplo, con el módulo langchain4j-google-ai-gemini, usarías GoogleAiGeminiChatModel.builder().apiKey(System.getenv("GOOGLE_API_KEY")).modelName("<model-id>").build().
En el método main(String[]), arrancamos el servidor MCP con STDIO, creamos una instancia del asistente con el método assistant y le enviamos dos mensajes.
El bloque try-with-resources cierra el cliente, lo que también detiene el proceso del servidor.
El ejemplo completo es un único fichero que puedes ejecutar con JBang: jbang LangChainMcpClient.java --assistant.
Para el primer mensaje, pedimos al asistente que ejecute un Pod con la imagen marcnuri/chuck-norris y exponga el puerto 8080.
El modelo llamó a la herramienta pods_run del servidor con la imagen y el puerto, y este es el resultado de la respuesta del asistente (he omitido sus dos últimos párrafos, que sugieren los siguientes pasos):
The Pod and Service have been successfully created and exposed on port 8080. Here are the details:
- **Pod Name**: `kubernetes-mcp-server-run-hlzqz`
- **Namespace**: `default`
- **Image**: `marcnuri/chuck-norris`
- **Port**: `8080` (exposed via container port)
- **Service Name**: `kubernetes-mcp-server-run-hlzqz`
- **Type**: `ClusterIP`
- **ClusterIP**: `10.96.78.72`
- **Port**: `8080` (TCP)
- **Selector**: Matches the pod label `app.kubernetes.io/name: kubernetes-mcp-server-run-hlzqz`
The Pod is currently in the **Pending** phase, which means it is waiting for a node to be assigned. Once assigned, it will start running and serve requests on port 8080.Los detalles salen del resultado de la herramienta, pero la explicación de la fase Pending es cosa del modelo, y solo es correcta a medias: la herramienta devuelve el Pod en el momento en que lo crea, y todo Pod nuevo permanece en Pending hasta que arrancan sus contenedores, lo que incluye esperar a un nodo y descargar la imagen.
Para el segundo mensaje, pedimos al asistente que liste los Pods del clúster como una tabla Markdown. Este es el resultado de la respuesta del asistente:
| NAME | NAMESPACE |
| --- | --- |
| kubernetes-mcp-server-run-hlzqz | default |
| nginx-5869d7778c-8spml | default |
| nginx-5869d7778c-c2hhm | default |
| coredns-668d6bf9bc-l6qbl | kube-system |
| coredns-668d6bf9bc-trd6s | kube-system |
| etcd-lc4j-refresh-control-plane | kube-system |
| kindnet-lj6l8 | kube-system |
| kube-apiserver-lc4j-refresh-control-plane | kube-system |
| kube-controller-manager-lc4j-refresh-control-plane | kube-system |
| kube-proxy-t7c85 | kube-system |
| kube-scheduler-lc4j-refresh-control-plane | kube-system |
| local-path-provisioner-7dc846544d-664q6 | local-path-storage |El nuevo Pod aparece en la lista, pero no porque el modelo lo recordara: el asistente no tiene memoria, y cada llamada a chat empieza una conversación nueva.
Añade un ChatMemory al AI service si quieres que el modelo recuerde los mensajes anteriores.
Conviene revisar lo que hacen los modelos pequeños.
Con la opción logEvents(true), puedes ver cada petición tools/call: en mis pruebas, Qwen3 4B siempre llamó a la herramienta correcta, pero en una de ellas listó todo el clúster con un field selector status.phase=Running que yo no había pedido, y que habría ocultado cualquier Pod pendiente o con fallos.
Con llama3.1:8b, una petición parecida falló: al pedirle los Pods del namespace default, el modelo llamó a pods_list con argumentos inventados y respondió con una llamada a herramienta en texto plano en lugar de la tabla.
Escribí más sobre esto en Otorgando Superpoderes a Small Language Models con MCP.
Limitar las herramientas que puede usar el modelo
McpToolProvider le da al modelo todas las herramientas que expone el servidor, incluidas las destructivas como pods_delete y resources_delete.
La forma más sencilla de mantener al modelo alejado de ellas está en el lado del servidor: el flag --read-only de Kubernetes MCP Server expone solo las herramientas anotadas como de solo lectura.
El modo de solo lectura impide cambios, no lecturas: herramientas como resources_get pueden seguir devolviendo Secrets, que llegan al modelo (y a su proveedor, si usas uno alojado); la opción denied_resources del servidor puede bloquearlos.
initStdioClient("npx", "-y", "kubernetes-mcp-server@latest", "--read-only")Con este flag, el cliente recibe 14 herramientas en lugar de 20.
En el lado del cliente, McpToolProvider puede filtrar las herramientas por nombre con filterToolNames("pods_list", "pods_get"), o con cualquier predicado.
LangChain4j expone las anotaciones de herramientas MCP de cada herramienta en sus metadatos, así que este filtro mantiene las mismas 14 herramientas de solo lectura:
import dev.langchain4j.mcp.client.McpToolMetadataKeys;
McpToolProvider.builder()
.mcpClients(client)
.filter((mcpClient, tool) -> Boolean.TRUE.equals(tool.metadata().get(McpToolMetadataKeys.READ_ONLY_HINT)))
.build();Eso sí, las anotaciones son pistas que da el servidor: filtra por ellas solo con servidores en los que confíes.
Testeo de servidores MCP con LangChain4j
Más allá de los casos de uso cotidianos, también uso esta configuración para testear implementaciones de servidores MCP en Java, como el servidor MCP de Kubernetes que escribí para el proyecto Quarkus MCP Servers. Al configurar un cliente MCP que se conecta al servidor, puedo simular interacciones del mundo real y verificar el comportamiento del servidor MCP.
A fecha de octubre de 2026, los tests de ese repositorio siguen fijados a LangChain4j 1.0.0-beta2 y al transporte SSE. Los fragmentos de código de esta sección muestran la misma configuración con la API actual de LangChain4j.
Utilizo estas técnicas con tres niveles de testing de integración:
1. Tests unitarios
Para testear unidades individuales de lógica, en aplicaciones Quarkus, puedes iniciar un cliente con el siguiente código:
@QuarkusTest
class MCPServerKubernetesTest {
@TestHTTPResource
URL url;
private McpClient mcpClient;
@BeforeEach
void setUpMcpClient() {
mcpClient = DefaultMcpClient.builder()
.clientName("test-mcp-client-kubernetes")
.toolExecutionTimeout(Duration.ofSeconds(10))
.transport(StreamableHttpMcpTransport.builder().url(url.toString() + "mcp").build())
.build();
}
}Dado que Quarkus proporciona la URL de la aplicación como un recurso de test, es fácil configurar un cliente MCP para testear.
La extensión HTTP de Quarkus MCP Server sirve el endpoint Streamable HTTP en /mcp por defecto.
Al combinar el cliente MCP con un servidor mock de Kubernetes como el proporcionado por el Cliente Java Kubernetes de Fabric8, puedes realizar solicitudes individuales utilizando el cliente y verificar el comportamiento de unidades específicas de lógica.
final var result = mcpClient.executeTool(
ToolExecutionRequest.builder().name("name_of_the_tool_in_test").arguments("{}").build());
assertThat(result.resultText()).contains("expected output");2. Tests de integración
La implementación de tests de integración más grandes para tu aplicación también es sencilla con LangChain4j y Quarkus. Partiendo de una aplicación ya compilada, puedes iniciar el servidor MCP real como un subproceso y conectarte a él utilizando el método de transporte STDIO.
En el siguiente fragmento de código, te muestro cómo lograr esto en Quarkus:
public class MCPServerKubernetesIT {
private static McpClient mcpClient;
@BeforeAll
static void setUpMcpClient() throws Exception {
mcpClient = DefaultMcpClient.builder()
.clientName("test-mcp-client-kubernetes")
.toolExecutionTimeout(Duration.ofSeconds(10))
.transport(StdioMcpTransport.builder().command(
List.of(
// Retrieve the java binary location:
ProcessHandle.current().info().command().orElseThrow(),
"-jar",
// Location of the built application (provided by Quarkus):
System.getProperty("java.jar.path")
)).logEvents(true).build())
.build();
}
}En este ejemplo, configuramos un cliente MCP utilizando el método de transporte STDIO para conectarnos a la aplicación Quarkus empaquetada. Esto indica al cliente MCP que inicie un subproceso real con la aplicación compilada y se comunique con ella a través de flujos de entrada/salida estándar.
Al igual que en el ejemplo de tests unitarios, puedes entonces ejecutar herramientas específicas en el servidor y verificar el comportamiento de la aplicación en su conjunto.
3. Tests de extremo a extremo
Para pruebas end-to-end, puedes emplear la misma configuración que en las pruebas de integración pero conectándote a un modelo real. Siguiendo la misma configuración que describí en la sección Ejemplo: un agente de IA en Java que usa Kubernetes MCP Server, puedes crear una prueba completa de extremo a extremo que simule interacciones del mundo real con tu aplicación.
Automatizando consultas de chat y comparando las respuestas con las salidas esperadas, puedes comprobar que las herramientas de tu servidor MCP están descritas lo bastante bien como para que un modelo las use.
No obstante, ten en cuenta la naturaleza no determinista de los modelos de IA, que puede llevar a respuestas diferentes para una misma entrada.
Debes considerar esto al escribir tus pruebas de extremo a extremo y permitir cierta flexibilidad en las salidas esperadas.
Comprobar las llamadas a herramientas que hizo el modelo es más fiable que comprobar su texto: declara el método del AI service como Result<String> chat(String userMessage), y result.toolExecutions() lista cada llamada a herramienta con sus argumentos y su resultado.
¿Puede LangChain4j crear también servidores MCP?
El módulo langchain4j-mcp es solo un cliente.
A fecha de octubre de 2026, el proyecto de la comunidad de LangChain4j publica un módulo langchain4j-community-mcp-server que expone tus métodos anotados con @Tool como un servidor MCP STDIO (Building a Java MCP stdio server).
Para un servidor con Streamable HTTP, yo uso la extensión Quarkus MCP Server de los ejemplos de testing anteriores.
Conclusión
El cliente MCP de LangChain4j permite a los desarrolladores Java dar a cualquier AI service de LangChain4j las herramientas de un servidor MCP. Ya estés utilizando un servidor MCP de terceros o desarrollando el tuyo propio, el cliente solo necesita un transporte, algunos ajustes opcionales y un proveedor de herramientas. Conectando tus aplicaciones Java a servidores MCP y modelos de lenguaje grandes (LLMs), puedes crear asistentes de IA que realicen tareas complejas e interactúen con herramientas y servicios externos.
En este artículo, te he mostrado cómo configurar un cliente MCP con LangChain4j con STDIO y Streamable HTTP, qué versión del protocolo elegir para cada uno y cómo integrarlo con un modelo local. También te he proporcionado algunas ideas sobre cómo usar LangChain4j para testear tus implementaciones de servidores MCP, desde pruebas unitarias hasta pruebas de extremo a extremo.
Los mismos servidores MCP funcionan también desde JavaScript, con LangChain.js o con AI SDK.
Puedes encontrar el código fuente de este artículo en GitHub.
Te Puede Interesar
- Introducción a Model Context Protocol (MCP): El Futuro de la Integración de IA
- MCP con LangChain.js: conecta agentes a servidores MCP
- Cliente MCP de AI SDK: conecta JavaScript a un servidor MCP
- Otorgando Superpoderes a Small Language Models con Model Context Protocol (MCP)
- MCP Tool Annotations: cada hint y su valor por defecto
