MCP con LangChain.js: conecta agentes a servidores MCP
Introducción
Para conectar un agente LangChain.js a un servidor Model Context Protocol (MCP) desde JavaScript o TypeScript, utilizas el paquete @langchain/mcp-adapters.
Su clase MCPAdapter arranca o se conecta a cada servidor MCP, y su método listTools() convierte las herramientas del servidor en herramientas de LangChain que pasas a createAgent.
El modelo de lenguaje grande (LLM) del agente puede entonces llamar a esas herramientas para leer datos en tiempo real y actuar en respuesta a las peticiones del usuario.
En este artículo, te mostraré cómo conectar una aplicación JavaScript a un servidor MCP utilizando LangChain.js, tanto con el transporte stdio como con Streamable HTTP, y cómo crear un agente que interactúe con un clúster de Kubernetes utilizando un modelo local.
He probado todos los pasos en octubre de 2026 con langchain 1.5.16, @langchain/mcp-adapters 2.0.1, @langchain/ollama 1.3.0, Kubernetes MCP Server v0.0.67 y el modelo qwen3:4b-instruct ejecutándose en Ollama, así que puedes ejecutar todos los ejemplos sin una API key.
Si tu código usa MultiServerMCPClient de la versión 1.x, consulta qué cambió en la 2.0.
Qué necesitas
Para seguir el artículo, necesitas:
- Node.js 22 o posterior (
@langchain/mcp-adapters2.x en sí necesita la 20.10 o posterior, pero Node.js 20 ya no tiene soporte). - Ollama con un modelo que soporte tool calling.
Yo utilicé
qwen3:4b-instruct(unos 2,5 GB), que puedes descargar conollama pull qwen3:4b-instruct. Asegúrate de que el servidor de Ollama está en marcha (la aplicación de escritorio lo arranca; si no, ejecutaollama serve). - Acceso a un clúster de Kubernetes a través de tu fichero kubeconfig. Cualquier clúster local, como los que crean kind o minikube, sirve.
Crea un nuevo proyecto e instala los paquetes:
npm init -y
npm install langchain @langchain/core @langchain/langgraph @langchain/mcp-adapters @langchain/ollama@langchain/core y @langchain/langgraph son peer dependencies de los adapters, y @langchain/ollama proporciona el modelo de chat para Ollama.
Configuración de los servidores MCP
Antes de poder usar las herramientas MCP con LangChain.js, necesitas clientes MCP que puedan comunicarse con los servidores MCP.
Con @langchain/mcp-adapters 2.x, no tienes que crear esos clientes tú mismo: describes cada servidor en un MCPAdapter, y el adapter crea y gestiona los clientes por ti.
El adapter elige el transporte a partir de la configuración de cada servidor: un command significa stdio, y una url significa Streamable HTTP.
Conexión a un servidor local mediante stdio
El transporte stdio es ideal para herramientas de línea de comandos e integraciones directas. Permite la comunicación con un servidor MCP que se ejecuta como un subproceso de tu aplicación. Este enfoque es particularmente útil para la ejecución local, lo que resulta práctico para agentes que realizan tareas en la misma máquina donde se está ejecutando el servidor.
El siguiente fragmento de código configura un MCPAdapter con un único servidor stdio:
import {MCPAdapter} from '@langchain/mcp-adapters';
const adapter = new MCPAdapter({
servers: {
kubernetes: {
command: 'npx',
args: ['-y', 'kubernetes-mcp-server@latest']
}
}
});En este ejemplo, estoy creando un adapter con un servidor llamado kubernetes que ejecuta el paquete de Kubernetes MCP Server usando npx.
El adapter lanza el comando como un subproceso y se comunica con él a través de sus flujos de entrada y salida estándar.
Estos son los componentes clave de la configuración del servidor stdio:
- La clave en el mapa
servers(kubernetes) es el nombre del servidor. El adapter la utiliza para identificar al servidor y, por defecto, como prefijo de los nombres de sus herramientas. command: El comando para ejecutar el servidor MCP.args: La lista de argumentos a pasar al comando.
El adapter no se conecta al crearlo; se conecta la primera vez que le pides las herramientas.
Nota
El transporte stdio no pasa todo tu entorno al proceso del servidor.
En Linux y macOS solo pasa HOME, LOGNAME, PATH, SHELL, TERM y USER (Windows tiene su propia lista).
Si seleccionas tu clúster con la variable de entorno KUBECONFIG, añade env: {KUBECONFIG: process.env.KUBECONFIG} a la configuración del servidor, o indica la ruta del kubeconfig como kubeconfig en un fichero TOML y pasa ese fichero con '--config', 'config.toml' en args.
Conexión a un servidor remoto mediante Streamable HTTP
El transporte Streamable HTTP es adecuado para servidores MCP que se ejecutan en un entorno remoto. Establece una conexión con el servidor MCP a través de HTTP utilizando un único endpoint para la comunicación bidireccional.
Nota
Antes de la versión 2025-03-26 del protocolo MCP, el transporte HTTP+SSE (Server-Sent Events) se utilizaba para conexiones remotas.
Desde entonces está obsoleto en favor de Streamable HTTP.
El adapter sigue conectándose a servidores que solo soportan SSE: con una url sin más, recurre a SSE cuando el servidor responde 404 o 405, y transport: 'sse' se salta el intento con Streamable HTTP.
Para probarlo en local, guarda la configuración del servidor en un fichero config.toml:
port = "8080"
bind_address = "127.0.0.1"Después, arranca Kubernetes MCP Server en modo HTTP en otro terminal:
npx -y kubernetes-mcp-server@latest --config config.tomlEl servidor escucha entonces peticiones Streamable HTTP en http://localhost:8080/mcp.
Lee su configuración del fichero TOML: desde la v0.0.68, rechaza los flags de línea de comandos que usan los tutoriales más antiguos, como --port, con un error unknown flag.
Por defecto, se enlaza a todas las interfaces de red (0.0.0.0), lo que expondría tu clúster a cualquiera que pueda acceder a tu máquina; bind_address = "127.0.0.1" lo mantiene en local.
El siguiente fragmento de código configura un MCPAdapter que se conecta a él:
import {MCPAdapter} from '@langchain/mcp-adapters';
const adapter = new MCPAdapter({
servers: {
kubernetes: {
url: 'http://localhost:8080/mcp'
}
}
});La única diferencia con la configuración stdio es la entrada del servidor: una url en lugar de un command.
Streamable HTTP es el transporte por defecto para los servidores con URL, así que no necesitas indicar transport: 'http'.
Para un servidor que requiere autenticación, la misma entrada admite headers o un authProvider para OAuth.
Un mismo adapter también puede combinar ambos tipos de servidores: añade una entrada por servidor al mapa servers, y el agente obtendrá las herramientas de todos ellos.
Cargar herramientas MCP como herramientas de LangChain.js
Ahora que el adapter conoce tu servidor MCP, puedes cargar sus herramientas y usarlas con LangChain.js.
Continuando con el fragmento anterior, el método listTools() se conecta a todos los servidores configurados, descubre sus herramientas y envuelve cada una como una herramienta de LangChain:
const tools = await adapter.listTools();
console.log(tools.map(tool => tool.name));
// [ 'kubernetes_events_list', 'kubernetes_namespaces_list', ... ]Por debajo, el adapter negocia la versión del protocolo con cada servidor, lista sus herramientas y crea para cada una de ellas una herramienta de LangChain con el mismo nombre, descripción y esquema de entrada.
Con la configuración por defecto, Kubernetes MCP Server v0.0.68 expone 19 herramientas por HTTP: desde esa versión, no activa configuration_view en modo HTTP.
Fíjate en el prefijo kubernetes_: desde la versión 2.0, el adapter antepone a cada nombre de herramienta el nombre de su servidor y un guion bajo, incluso cuando solo hay un servidor.
Así se evitan colisiones cuando dos servidores exponen una herramienta con el mismo nombre.
Puedes indicar prefixToolNameWithServerName: false en la configuración del adapter para mantener los nombres originales.
El adapter mantiene las conexiones abiertas mientras tu agente utiliza las herramientas.
Cuando termines, llama a await adapter.close() para cerrarlas y detener los procesos de servidor que haya arrancado.
Usar tu propio cliente MCP con loadMcpTools
Si tu aplicación ya gestiona su propio cliente MCP, la función independiente loadMcpTools adapta las herramientas de ese cliente sin ceder la conexión a un MCPAdapter.
Desde @langchain/mcp-adapters 2.0, espera un cliente de la versión 2 del SDK de MCP para TypeScript, que puedes instalar con npm install @modelcontextprotocol/client:
import {Client} from '@modelcontextprotocol/client';
import {StdioClientTransport} from '@modelcontextprotocol/client/stdio';
import {loadMcpTools} from '@langchain/mcp-adapters';
const client = new Client(
{name: 'blog.marcnuri.com', version: '1.0.0'},
{versionNegotiation: {mode: 'auto'}}
);
await client.connect(new StdioClientTransport({
command: 'npx',
args: ['-y', 'kubernetes-mcp-server@latest']
}));
const tools = await loadMcpTools('kubernetes', client);Para un servidor remoto, importa StreamableHTTPClientTransport desde @modelcontextprotocol/client y pásale new URL('http://localhost:8080/mcp') en su lugar.
Estos son los componentes clave del ejemplo:
Client: El cliente MCP, con un nombre y una versión que lo identifican ante el servidor.versionNegotiation: {mode: 'auto'}le permite usar la última revisión del protocolo (2026-07-28) cuando el servidor la soporta, y recurrir a la anterior cuando no; sin esta opción, el SDK solo habla las revisiones antiguas. En mis pruebas, el cliente negoció la 2026-07-28 con Kubernetes MCP Server mediante stdio, y la 2025-11-25 mediante Streamable HTTP.StdioClientTransport: El transporte stdio, que lanza el servidor como un subproceso.loadMcpTools: Lista las herramientas del cliente y las devuelve como herramientas de LangChain. El primer argumento es el nombre del servidor; a diferencia deMCPAdapter,loadMcpToolsno añade prefijos a los nombres de las herramientas salvo que se lo pidas.
Este cliente es responsabilidad tuya: ciérralo con await client.close() cuando termines.
Crear un agente LangChain.js con createAgent y LangGraph.js
Ya tienes todas las piezas para crear un agente que pueda usar las herramientas MCP.
Desde LangChain.js 1.0 (octubre de 2025), createAgent del paquete langchain es la forma estándar de crear uno.
Se ejecuta sobre LangGraph.js y sustituye al createReactAgent predefinido de LangGraph, que ahora está obsoleto.
Aquí tienes un ejemplo completo que crea un agente capaz de interactuar con un clúster de Kubernetes utilizando Kubernetes MCP Server y un modelo local ejecutándose en Ollama:
import {createAgent} from 'langchain';
import {ChatOllama} from '@langchain/ollama';
import {MCPAdapter} from '@langchain/mcp-adapters';
const adapter = new MCPAdapter({
servers: {
kubernetes: {
command: 'npx',
args: ['-y', 'kubernetes-mcp-server@latest']
}
}
});
try {
const tools = await adapter.listTools();
const agent = createAgent({
model: new ChatOllama({model: 'qwen3:4b-instruct'}),
tools
});
const listPods = await agent.invoke({
messages: [{
role: 'user',
content: 'List all pods in my cluster and output their name and namespace as a Markdown table'
}]
});
console.log(listPods.messages.at(-1).text);
} finally {
await adapter.close();
}Puedes ejecutarlo con node kubernetes-agent.mjs.
En este ejemplo, creo un asistente muy sencillo que conecta las herramientas de Kubernetes MCP Server con el modelo qwen3:4b-instruct ejecutándose en tu máquina.
Estos son los componentes clave del ejemplo del agente:
ChatOllama:
Un modelo de chat de LangChain que se comunica con el servidor local de Ollama (http://127.0.0.1:11434por defecto).model: El nombre del modelo de Ollama a usar.
adapter.listTools():
Carga las herramientas MCP de Kubernetes MCP Server como se describió en la sección anterior.createAgent:
Crea un agente de LangChain utilizando el modelo y las herramientas que has cargado.invoke:
Invoca el agente con una solicitud de usuario para listar todos los pods en el clúster de Kubernetes. El agente utilizará las herramientas para realizar la acción y devolver el resultado.listPods.messages:
El estado del agente tras la ejecución. El ejemplo imprime el texto del último mensaje, que contiene la respuesta final del modelo.adapter.close():
Cierra la conexión y detiene el proceso del servidor, incluso si el agente falla.
Consejo
Cualquier modelo de chat de LangChain que soporte tool calling puede sustituir a ChatOllama.
Para un modelo alojado como Gemini de Google, instala @langchain/google-genai, añade import {ChatGoogleGenerativeAI} from '@langchain/google-genai' y usa new ChatGoogleGenerativeAI({model: 'gemini-2.5-flash'}) con tu GOOGLE_API_KEY.
El agente sigue un patrón ReAct (Reasoning and Acting, razonar y actuar), alternando entre razonar sobre qué hacer a continuación y actuar con las herramientas disponibles. En este caso, el agente puede usar las herramientas proporcionadas por Kubernetes MCP Server para interactuar con tu clúster de Kubernetes.
Ejecuté el ejemplo contra un clúster local de pruebas simulado cuyos únicos Pods eran los de un deployment de nginx de dos réplicas, y el resultado fue (en un clúster de kind o minikube, la lista incluye también los Pods de kube-system):
| NAME | NAMESPACE |
|--------------------------------------|-----------|
| nginx-7f8fbb96d-kjc5p | default |
| nginx-7f8fbb96d-l5svd | default |El array listPods.messages contiene la lista completa de mensajes intercambiados durante la ejecución.
En este caso, fueron cuatro: la petición del usuario, la llamada del modelo a la herramienta kubernetes_pods_list, el resultado de la herramienta y la respuesta final del modelo.
Lo interesante de este enfoque es que el agente decide qué herramientas usar en función de la petición del usuario. Por ejemplo, si el usuario pide listar pods, el agente identifica que necesita la herramienta de Kubernetes que obtiene información sobre los pods y luego formatea el resultado como una tabla Markdown.
Eso sí, los modelos pequeños necesitan algo de ayuda.
qwen3:4b-instruct llamó a la herramienta correcta en todas mis ejecuciones, pero normalmente añadía un filtro status.phase=Running que nadie había pedido, lo que ocultaría los pods en cualquier otro estado, y las columnas de la tabla cambiaban de una ejecución a otra.
Otros modelos pequeños que probé enviaban valores vacíos o null en los argumentos opcionales, que el adapter rechaza porque no cumplen el esquema de entrada de la herramienta.
El agente recibe el error como resultado de la herramienta, así que el modelo puede reintentarlo, pero los modelos pequeños rara vez se recuperaban: granite4 solía repetir la misma llamada y responder con una tabla de relleno, y llama3.2:3b se rendía.
Expliqué cómo sacar el máximo partido a los modelos pequeños en Otorgando Superpoderes a Small Language Models con MCP.
Kubernetes MCP Server también expone herramientas que borran o modifican recursos de tu clúster.
Para experimentar de forma segura, establece read_only = true en un fichero TOML y añade '--config', 'read-only.toml' a sus args, de modo que solo exponga las herramientas que no cambian nada.
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.
Actualizar desde @langchain/mcp-adapters 1.x
Anthropic presentó MCP en noviembre de 2024, y rápidamente se convirtió en la forma estándar de exponer herramientas a aplicaciones de inteligencia artificial (IA).
En marzo de 2025, la comunidad de LangChain lanzó los MCP adapters para LangChain.js, una librería JavaScript para crear aplicaciones potenciadas por LLMs; los adapters empezaron como un proyecto independiente y ahora forman parte del repositorio principal de LangChain.js.
@langchain/mcp-adapters 2.0 (octubre de 2026) pasó a la versión 2 del SDK de MCP para TypeScript, que añade la revisión 2026-07-28 de la especificación MCP sin dejar de funcionar con servidores más antiguos, con MCPAdapter como nuevo punto de entrada.
Escribí la primera versión de este artículo en abril de 2025, con clientes MCP creados a mano, el transporte SSE, el createReactAgent de LangGraph y GPT-4o mini de OpenAI a través de GitHub Models.
En enero de 2026, lo actualicé a Streamable HTTP, createAgent y Gemini de Google.
Si seguiste una versión anterior de este artículo, o cualquier tutorial que use MultiServerMCPClient, esto es lo que cambió en @langchain/mcp-adapters 2.0:
| 1.x | 2.x |
|---|---|
MultiServerMCPClient | MCPAdapter |
mcpServers: {...} | servers: {...} |
getTools() | listTools() |
Nombres de herramientas sin prefijo (pods_list) | Nombres de herramientas con prefijo (kubernetes_pods_list) |
Cliente de @modelcontextprotocol/sdk | Cliente de @modelcontextprotocol/client |
Los nombres antiguos de clases y métodos siguen funcionando, pero están obsoletos.
Pasar a loadMcpTools un cliente del antiguo paquete @modelcontextprotocol/sdk no funciona: falla con TypeError: client.getProtocolEra is not a function.
Cambia los imports a @modelcontextprotocol/client (y @modelcontextprotocol/client/stdio para el transporte stdio), como se muestra más arriba.
Los nombres de herramientas con prefijo también afectan a todo lo que haga referencia a una herramienta por su nombre, como prompts o reglas de aprobación human-in-the-loop.
La guía de migración oficial cubre el resto de cambios.
Conclusión
En este artículo, te he mostrado cómo conectar tus aplicaciones JavaScript a un servidor MCP utilizando LangChain.js.
He cubierto cómo configurar servidores stdio y Streamable HTTP con MCPAdapter, cómo cargar sus herramientas (o adaptar las herramientas de tu propio cliente MCP con loadMcpTools) y cómo unir todo con createAgent y un modelo local.
Con los MCP adapters, cualquiera de los muchos servidores MCP disponibles se convierte en un conjunto de herramientas que tus agentes LangChain.js pueden usar con unas pocas líneas de configuración.
Puedes encontrar el código fuente de este artículo en GitHub.
Te Puede Interesar
- Cliente MCP de AI SDK: conecta JavaScript a un servidor MCP
- Cliente MCP de LangChain4j: conecta Java a un servidor MCP
- Introducción a Model Context Protocol (MCP): El Futuro de la Integración de IA
- Otorgando Superpoderes a Small Language Models con Model Context Protocol (MCP)
- MCP Tool Annotations: cada hint y su valor por defecto
