Cliente MCP de AI SDK: conecta JavaScript a un servidor MCP
Introducción
Para conectar una aplicación JavaScript a un servidor Model Context Protocol (MCP) con Vercel AI SDK, creas un cliente MCP con createMCPClient del paquete @ai-sdk/mcp (experimental_createMCPClient en versiones anteriores), pasas las herramientas que devuelve a generateText o streamText, y cierras el cliente cuando terminas.
El modelo decide entonces a qué herramientas del servidor llamar, y AI SDK las ejecuta y le devuelve los resultados al modelo.
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. Vercel AI SDK es un toolkit de TypeScript con una creciente lista de proveedores de modelos compatibles, lo que lo convierte en una excelente alternativa a la librería LangChain.js.
En este artículo, te mostraré cómo conectar tus aplicaciones JavaScript a un servidor MCP utilizando AI SDK.
Te explicaré cómo configurar el cliente MCP con stdio y Streamable HTTP, configurar un proveedor de modelos y hacer prompts al modelo utilizando la función generateText.
He probado cada paso en octubre de 2026 con AI SDK 7.0.140, @ai-sdk/mcp 2.0.74, 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é import necesitas: experimental_createMCPClient o createMCPClient?
Vercel añadió un cliente MCP experimental en AI SDK 4.2 (marzo de 2025), y escribí la primera versión de este artículo unas semanas después, en abril de 2025.
El cliente se movió a su propio paquete, @ai-sdk/mcp, en octubre de 2025, y AI SDK 6 (diciembre de 2025) lo estabilizó y eliminó el prefijo experimental_, así que el import de los tutoriales más antiguos depende de la versión de AI SDK para la que se escribieron:
| Versión de AI SDK | Import del cliente MCP |
|---|---|
| 4.2 a 5.0.78 | experimental_createMCPClient de ai |
| 5.0.79 a 5.x | experimental_createMCPClient de @ai-sdk/mcp (0.x) |
| 6 y 7 | createMCPClient de @ai-sdk/mcp (1.x y 2.x) |
A fecha de octubre de 2026, @ai-sdk/mcp todavía exporta el nombre experimental_createMCPClient como alias, pero el código nuevo debería utilizar createMCPClient.
AI SDK 7 (junio de 2026) convirtió todos los paquetes en ESM-only y renombró algunas de las funciones que utilizo en este artículo.
Si estás actualizando código de AI SDK 6, estos son los cambios de su guía de migración que afectan a este artículo:
stepCountIsahora esisStepCount(el nombre anterior sigue funcionando como alias).- La opción
namedel cliente está obsoleta en favor declientName, que las últimas versiones de AI SDK 6 ya aceptan (namesigue funcionando). - El transporte HTTP rechaza las redirecciones por defecto; configura
redirect: 'follow'si tu servidor depende de ellas. - Todos los paquetes son ESM-only y necesitan Node.js 22 o posterior.
Configuración del proyecto
Los paquetes de AI SDK 7 son ESM-only y necesitan Node.js 22 o posterior (compruébalo con node --version).
Crea un proyecto y configúralo para utilizar módulos ES:
npm init -y
npm pkg set type=moduleInstala AI SDK, su cliente MCP, el paquete cliente del SDK oficial de MCP para TypeScript (para el transporte stdio) y el proveedor de Ollama:
npm install ai @ai-sdk/mcp @modelcontextprotocol/client ollama-ai-provider-v2Los 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 necesita un clúster con el que comunicarse.
Utiliza tu fichero kubeconfig por defecto, así que cualquier clúster sirve; yo utilicé un clúster local de kind, que kind create cluster crea y añade a ese fichero.
Creación de los clientes MCP de AI SDK
Para interactuar con un servidor MCP, primero necesitamos crear un cliente MCP.
AI SDK proporciona una función llamada createMCPClient en el paquete @ai-sdk/mcp que nos permite establecer esta conexión.
La especificación de MCP define dos transportes estándar: stdio y Streamable HTTP. Veamos cómo crear un cliente para cada uno de ellos.
Configuración de un cliente de transporte STDIO
El método de transporte STDIO nos permite lanzar un proceso local y comunicarnos con él a través de los flujos de entrada y salida estándar. Esto es útil para ejecutar servidores o procesos MCP locales que exponen las capacidades del sistema local.
El siguiente fragmento de código muestra cómo configurar un cliente de transporte STDIO para el servidor MCP de Kubernetes:
import {createMCPClient} from '@ai-sdk/mcp';
import {StdioClientTransport} from '@modelcontextprotocol/client/stdio';
const initStdioClient = async () => {
const transport = new StdioClientTransport({
command: 'npx',
args: ['-y', 'kubernetes-mcp-server@latest']
});
return createMCPClient({clientName: 'blog.marcnuri.com', transport});
};En este fragmento, estamos creando un cliente MCP que ejecuta Kubernetes MCP Server utilizando el comando npx.
Estos son los pasos clave para configurar el cliente de transporte STDIO:
- Importar los módulos necesarios de los paquetes
@ai-sdk/mcpy@modelcontextprotocol/client. - Crear una nueva instancia de
StdioClientTransport, pasando el comando y los argumentos para ejecutar el servidor MCP. - Llamar a
createMCPClientcon la instancia de transporte para crear el cliente MCP y establecer la conexión.clientNamees opcional; es el nombre con el que el cliente se identifica ante el servidor.
Los tutoriales más antiguos, y la documentación de AI SDK a fecha de octubre de 2026, importan el mismo transporte desde @modelcontextprotocol/sdk/client/stdio.js, la versión 1 del SDK de MCP para TypeScript, que sigue funcionando.
Nota
El transporte no pasa todo tu entorno al proceso del servidor: solo unas pocas variables, como HOME, PATH y USER (en Windows, sus equivalentes).
Si el servidor necesita alguna otra, como KUBECONFIG o la configuración del proxy para npx, añádela con la opción env del transporte, que se combina con esas variables por defecto, por ejemplo env: {KUBECONFIG: process.env.KUBECONFIG}.
AI SDK también incluye su propio transporte stdio, Experimental_StdioMCPTransport en @ai-sdk/mcp/mcp-stdio.
Antes del handshake clásico, consulta al servidor si soporta la nueva revisión stateless del protocolo (2026-07-28) y abandona esa consulta pasado un segundo.
En mis pruebas con la v2.0.74, npx -y kubernetes-mcp-server@latest tardaba más que eso en arrancar el servidor, y la conexión fallaba con el error duplicate "initialize" received.
La conexión funcionó en cuanto configuré protocolVersionDiscovery: false en createMCPClient, o cuando el servidor arrancaba rápido desde una instalación local.
El transporte del SDK de MCP que te he mostrado utiliza el handshake clásico desde el principio, así que prefiero seguir con él.
Configuración de un cliente de transporte Streamable HTTP
El método de transporte Streamable HTTP nos permite conectarnos a un servidor MCP remoto a través de HTTP. Esto es útil cuando tienes un servidor MCP que ya está ejecutándose como un servicio al que quieres conectarte.
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.
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 lee su configuración de este 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.
Sin 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:
import {createMCPClient} from '@ai-sdk/mcp';
const initHttpClient = async () => {
return createMCPClient({
clientName: 'blog.marcnuri.com',
transport: {
type: 'http',
url: 'http://localhost:8080/mcp'
}
});
};En este fragmento, estamos creando un cliente MCP que se conecta a un servidor local que se ejecuta en el puerto 8080 utilizando el protocolo Streamable HTTP. Este enfoque es más adecuado para entornos de producción o cuando tienes un servidor MCP dedicado en ejecución.
Nota
En entornos de producción, la URL debe apuntar a la dirección real de tu servidor MCP (que también debería estar habilitado para HTTPS).
El transporte también acepta headers (por ejemplo, una cabecera Authorization) y un authProvider de OAuth.
Desde AI SDK 7, rechaza las redirecciones HTTP por defecto; configura redirect: 'follow' si tu servidor depende de ellas.
Estos son los pasos clave para configurar el cliente de transporte Streamable HTTP:
- Importar el módulo necesario del paquete
@ai-sdk/mcp. - Llamar a
createMCPClientcon la configuración de transporte, especificando el tipo comohttpy proporcionando la URL del servidor MCP. - La función devuelve una instancia de cliente MCP que se puede utilizar para interactuar con el servidor remoto.
Fíjate en que el transporte HTTP es mucho más sencillo de configurar que el transporte STDIO: AI SDK lo incluye, así que no necesitas el SDK de MCP.
Configuración del proveedor y el modelo de AI SDK
Una vez que tenemos el cliente MCP configurado, necesitamos configurar el proveedor de AI SDK y el modelo que utilizará las herramientas del servidor MCP. AI SDK tiene una larga lista de proveedores compatibles; en este caso, utilizaremos el proveedor de Ollama de la comunidad para ejecutar un modelo en local.
El siguiente fragmento de código muestra cómo configurar el proveedor de Ollama con el modelo Qwen3 4B:
import {ollama} from 'ollama-ai-provider-v2';
const model = ollama('qwen3:4b-instruct');En este fragmento, estamos utilizando la instancia por defecto del proveedor de Ollama y especificando el modelo que queremos utilizar:
- La instancia
ollamapor defecto se conecta a un servidor local de Ollama enhttp://127.0.0.1:11434/api. Si el tuyo se ejecuta en otro sitio, crea tu propia instancia concreateOllama({baseURL: '...'}). - La función
ollamase llama con el nombre del modelo para crear una instancia del modelo que se puede utilizar para generar texto.
El modelo debe soportar tool calling, y los modelos pequeños varían mucho en lo bien que lo hacen. Escribí sobre esto en Otorgando Superpoderes a Small Language Models con MCP.
Consejo
Cambiar a un modelo alojado en la nube solo afecta a estas dos líneas.
Por ejemplo, con el proveedor de Google (@ai-sdk/google), importarías google y crearías el modelo con google('<model-id>'), que lee la API key de la variable de entorno GOOGLE_GENERATIVE_AI_API_KEY.
En AI SDK 7, la función createGoogleGenerativeAI del proveedor de Google ahora se llama createGoogle.
Hacer prompts al modelo con generateText
Ahora que tenemos todos los componentes configurados, podemos juntar las piezas para hacer prompts al modelo y dejar que interactúe con las herramientas del servidor MCP.
En este ejemplo, vamos a generar texto pidiendo al modelo que liste todos los pods de Kubernetes en formato de tabla Markdown.
El siguiente fragmento de código muestra las partes relevantes del pipeline:
import {generateText, isStepCount} from 'ai';
import {ollama} from 'ollama-ai-provider-v2';
const assistant = async () => {
const mcpClient = await initStdioClient();
try {
const tools = await mcpClient.tools();
const model = ollama('qwen3:4b-instruct');
const result = await generateText({
model,
tools,
stopWhen: isStepCount(10),
messages: [{
role: 'user',
content: 'List all pods in my cluster and output their name and namespace as a Markdown table'
}]
});
console.log(result.text);
} finally {
await mcpClient.close();
}
};
assistant().catch(err => {
console.error('Error:', err);
});En este fragmento, estamos creando un asistente que conecta el modelo Qwen3 4B a las herramientas del servidor MCP de Kubernetes y le hace un prompt sencillo.
Estos son los componentes clave de este ejemplo:
- Primero inicializamos el cliente STDIO y obtenemos las herramientas disponibles llamando a
mcpClient.tools(). Esto lista todas las herramientas que ofrece el servidor (20 con los toolsets por defecto de Kubernetes MCP Server) y las convierte en herramientas de AI SDK. - Luego llamamos a la función
generateTextcon los siguientes parámetros:model: La instancia del modelo que creamos anteriormente.tools: Las herramientas disponibles desde el cliente del servidor MCP.stopWhen: Una condición que determina cuándo detener el bucle de generación. UsamosisStepCount(10)para limitar el modelo a un máximo de 10 pasos.
Por defecto,generateTextejecuta un único paso: AI SDK ejecutaría la herramienta que pide el modelo, pero el modelo no tendría otro paso para convertir el resultado en una respuesta, así queresult.textquedaría vacío. Un valor mayor que 1 garantiza que el modelo pueda procesar el prompt inicial y los prompts posteriores con los resultados de la ejecución de las herramientas.messages: Un array de mensajes que representan el historial de la conversación. En este caso, proporcionamos un solo mensaje del usuario pidiendo al modelo que liste todos los pods en el clúster y formatee la salida como una tabla Markdown.
- Por último, mostramos el texto generado en la consola y cerramos el cliente en un bloque
finally, para que el proceso del servidor se detenga aunque la generación falle.
El resultado del ejemplo será similar a esto:
| NAMESPACE | NAME |
|----------|------|
| default | nginx-6f5fc479d9-j25wp |
| default | nginx-6f5fc479d9-vq4r9 |
| kube-system | coredns-668d6bf9bc-2q9pp |
| kube-system | coredns-668d6bf9bc-r2jg2 |
| kube-system | etcd-ai-sdk-refresh-control-plane |
| kube-system | kindnet-zncdz |
| kube-system | kube-apiserver-ai-sdk-refresh-control-plane |
| kube-system | kube-controller-manager-ai-sdk-refresh-control-plane |
| kube-system | kube-proxy-rpsdh |
| kube-system | kube-scheduler-ai-sdk-refresh-control-plane |
| local-path-storage | local-path-provisioner-7dc846544d-8xlh6 |result.text solo contiene la respuesta final del modelo.
result.steps contiene cada paso del bucle, incluidas las llamadas a herramientas y sus resultados, que es donde puedes comprobar lo que el modelo hizo realmente.
Esa comprobación es importante con un modelo pequeño.
En mis pruebas, Qwen3 4B siempre llamó a la herramienta pods_list, pero cada vez que le pedí columnas concretas, añadió un field selector status.phase=Running que no le había pedido, lo que habría ocultado cualquier pod pendiente o con errores.
Cuando, en cambio, le pedí todas las columnas, llamó a la herramienta sin filtros, pero copió mal la IP de un pod al reescribir la tabla de 13 columnas.
En mi portátil, cada ejecución tardó entre 25 y 40 segundos.
Limitar las herramientas que puede usar el modelo
mcpClient.tools() le entrega 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: la opción 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.
Actívala en un fichero TOML y pásale el fichero al servidor con --config:
read_only = trueargs: ['-y', 'kubernetes-mcp-server@latest', '--config', 'read-only.toml']Con esta opción, el cliente recibe 14 herramientas en lugar de 20.
En el lado del cliente, AI SDK expone las anotaciones de herramientas MCP de cada herramienta en sus metadatos, y su opción toolApproval te permite exigir la aprobación del usuario para las herramientas que no están marcadas como de solo lectura.
Eso sí, las anotaciones son pistas que da el servidor: fíate de ellas solo con servidores en los que confíes, ya que un servidor puede marcar una herramienta destructiva como de solo lectura y saltarse la aprobación.
Conclusión
En este artículo, te he mostrado cómo conectarte a un servidor MCP desde JavaScript utilizando Vercel AI SDK.
Hemos visto cómo configurar tanto clientes de transporte STDIO como Streamable HTTP, configurar un modelo local con el proveedor de Ollama y hacer prompts al modelo utilizando la función generateText para generar resultados útiles.
Esta arquitectura modular ilustra la flexibilidad del SDK: cambiar el transporte o el proveedor de modelos solo afecta a unas pocas líneas, y el resto del código sigue igual. Al seguir estos pasos, puedes integrar tus aplicaciones JavaScript con un servidor MCP y permitir que los LLMs interactúen con herramientas y sistemas externos.
A medida que el ecosistema MCP madura, los mismos servidores MCP funcionan desde AI SDK, desde LangChain.js o desde cualquier otro cliente MCP.
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 LangChain4j: conecta Java 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
