tutoriales·14 min de lectura

MCP (Model Context Protocol): guía para Conectar IA con tus APIs

Aprende qué es MCP, cómo funciona y cómo crear tu primer servidor MCP con TypeScript. El estandar universal para conectar modelos de IA con herramientas, APIs y bases de datos.

MCP (Model Context Protocol): guía para Conectar IA con tus APIs

El MCP (Model Context Protocol) es un estandar abierto que resuelve un problema concreto: cada modelo de IA tiene su propia forma de conectarse a herramientas externas. OpenAI usa function calling con un formato. Anthropic usa otro. Google tiene el suyo. Si quieres que tu herramienta funcione con todos, tienes que implementar la integración tres veces. MCP estandariza esa conexión con un solo protocolo universal.

Creado por Anthropic y donado a la Linux Foundation, MCP ya fue adoptado por OpenAI, Google y Microsoft. No es una especificación teorica -- es el protocolo que usan Claude Desktop, Cursor, Windsurf y decenas de herramientas en producción.

En este tutorial vas a entender cómo funciona MCP, construir tu primer servidor con TypeScript, conectarlo a Claude Desktop y usarlo con Vercel AI SDK en una aplicación Next.js.

El problema que resuelve MCP

Sin MCP, conectar un modelo de IA a tus herramientas se ve así:

typescript
// Para OpenAI: un formato
const tools = [{
  type: "function",
  function: {
    name: "buscar_usuario",
    parameters: { type: "object", properties: { email: { type: "string" } } }
  }
}]
 
// Para Anthropic: otro formato
const tools = [{
  name: "buscar_usuario",
  input_schema: { type: "object", properties: { email: { type: "string" } } }
}]
 
// Para Google Gemini: otro más
const tools = [{
  functionDeclarations: [{
    name: "buscar_usuario",
    parameters: { type: "object", properties: { email: { type: "string" } } }
  }]
}]

Tres implementaciones para la misma funcionalidad. Y cada vez que agregas una herramienta nueva, tienes que replicar el trabajo.

MCP resuelve esto con una analogia que Anthropic usa en su documentación oficial: es el USB-C de la IA. Antes de USB-C, cada fabricante tenia su propio conector. Ahora conectas cualquier dispositivo con el mismo cable. MCP hace lo mismo para la conexión entre modelos de IA y herramientas externas.

cómo funciona MCP: arquitectura

La arquitectura de MCP tiene tres capas:

plaintext
Host (aplicación de IA)
  |
  +-- Client (maneja la conexión)
        |
        +-- Server (expone capacidades)
              |
              +-- Tools (funciones que la IA puede ejecutar)
              +-- Resources (datos que la IA puede leer)
              +-- Prompts (plantillas reutilizables)

Cada pieza tiene un rol definido:

  • Host: la aplicación donde corre el modelo. Claude Desktop, Cursor, tu app de Next.js, cualquier cosa que use un LLM.
  • Client: vive dentro del Host. Se encarga de establecer y mantener la conexión con el servidor MCP. Maneja el ciclo de vida de la comunicación.
  • Server: un proceso que expone herramientas, recursos y prompts al modelo a través del protocolo MCP. Puede ser un script local o un endpoint HTTP.
Un Host, múltiples Servers

Un Host puede conectarse a varios servidores MCP al mismo tiempo. Por ejemplo, Claude Desktop puede tener un servidor para acceder a tu base de datos, otro para tu API de GitHub y otro para el sistema de archivos. Cada servidor se especializa en una cosa.

La comunicación entre Client y Server usa JSON-RPC 2.0. No necesitas implementar el protocolo manualmente -- el SDK oficial se encarga de eso.

Conceptos fundamentales: Tools, Resources y Prompts

MCP define tres tipos de capacidades que un servidor puede exponer.

Tools: funciones que la IA puede ejecutar

Los Tools son el concepto más usado. Son funciones que el modelo puede decidir llamar basandose en el contexto de la conversación. Piensa en ellas como function calling, pero estandarizado.

typescript
// Ejemplo conceptual de un Tool
{
  name: "buscar_usuario",
  description: "Busca un usuario en la base de datos por email",
  inputSchema: {
    type: "object",
    properties: {
      email: { type: "string", description: "Email del usuario" }
    },
    required: ["email"]
  }
}

Cuando el usuario le dice a Claude "busca al usuario con email ana@mail.com", el modelo identifica que tiene un Tool disponible para eso, genera los argumentos correctos y lo ejecuta. El resultado vuelve al modelo para que lo interprete y responda.

Resources: datos que la IA puede leer

Los Resources exponen datos de solo lectura. A diferencia de los Tools, los Resources no ejecutan lógica -- simplemente proveen información que el modelo puede usar como contexto.

typescript
// Ejemplo conceptual de un Resource
{
  uri: "db://usuarios/lista",
  name: "Lista de usuarios",
  description: "Todos los usuarios registrados en el sistema",
  mimeType: "application/json"
}

Un Resource puede ser el contenido de un archivo, los registros de una tabla, la configuración de un proyecto, o cualquier dato que el modelo necesite para responder mejor.

Prompts: plantillas reutilizables

Los Prompts son templates predefinidos que el servidor expone al cliente. Son útiles para estandarizar interacciones comunes.

typescript
// Ejemplo conceptual de un Prompt
{
  name: "revisar_codigo",
  description: "Analiza código y sugiere mejoras",
  arguments: [
    { name: "lenguaje", description: "Lenguaje de programación", required: true },
    { name: "código", description: "código a revisar", required: true }
  ]
}

En la práctica, los Tools son la funcionalidad que más vas a usar. Los Resources son útiles cuando tu servidor maneja datos que el modelo necesita consultar frecuentemente. Los Prompts son más de nicho.

Configuración del proyecto

Vamos a crear un servidor MCP desde cero con TypeScript. Lo primero es preparar el proyecto.

Terminal
$ mkdir mi-servidor-mcp && cd mi-servidor-mcp && npm init -y

Instala el SDK oficial de MCP y las dependencias necesarias:

Terminal
$ npm install @modelcontextprotocol/sdk zod
Terminal
$ npm install -D typescript @types/node tsx

Configura TypeScript:

json
// tsconfig.json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "Node16",
    "moduleResolution": "Node16",
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true
  },
  "include": ["src/**/*"]
}

La estructura del proyecto queda así:

Estructura de archivos

Tu primer servidor MCP

Vamos a construir un servidor que expone dos capacidades: un Tool para buscar usuarios en una base de datos simulada y un Resource para leer la lista completa de usuarios.

typescript
// src/index.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
 
// Base de datos simulada
const usuarios = [
  { id: 1, nombre: "Ana Garcia", email: "ana@mail.com", rol: "admin" },
  { id: 2, nombre: "Carlos Lopez", email: "carlos@mail.com", rol: "editor" },
  { id: 3, nombre: "Maria Torres", email: "maria@mail.com", rol: "usuario" },
  { id: 4, nombre: "Pedro Ruiz", email: "pedro@mail.com", rol: "editor" },
];
 
// Crear instancia del servidor
const server = new McpServer({
  name: "mi-servidor-usuarios",
  version: "1.0.0",
});
 
// Tool: buscar usuario por email
server.tool(
  "buscar_usuario",
  "Busca un usuario en la base de datos por su dirección de email",
  { email: z.string().email().describe("Email del usuario a buscar") },
  async ({ email }) => {
    const usuario = usuarios.find(
      (u) => u.email.toLowerCase() === email.toLowerCase()
    );
 
    if (!usuario) {
      return {
        content: [
          {
            type: "text",
            text: `No se encontro un usuario con el email: ${email}`,
          },
        ],
      };
    }
 
    return {
      content: [
        {
          type: "text",
          text: JSON.stringify(usuario, null, 2),
        },
      ],
    };
  }
);
 
// Tool: buscar usuarios por rol
server.tool(
  "buscar_por_rol",
  "Busca todos los usuarios que tengan un rol específico",
  {
    rol: z
      .enum(["admin", "editor", "usuario"])
      .describe("Rol a filtrar: admin, editor o usuario"),
  },
  async ({ rol }) => {
    const resultado = usuarios.filter((u) => u.rol === rol);
 
    return {
      content: [
        {
          type: "text",
          text:
            resultado.length > 0
              ? JSON.stringify(resultado, null, 2)
              : `No hay usuarios con el rol: ${rol}`,
        },
      ],
    };
  }
);
 
// Resource: lista completa de usuarios
server.resource("usuarios://lista", "Lista completa de usuarios registrados", async (uri) => ({
  contents: [
    {
      uri: uri.href,
      mimeType: "application/json",
      text: JSON.stringify(usuarios, null, 2),
    },
  ],
}));
 
// Iniciar el servidor con transporte stdio
async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
  console.error("Servidor MCP de usuarios iniciado");
}
 
main().catch(console.error);

Agrega el script de ejecución en tu package.json:

json
{
  "scripts": {
    "start": "tsx src/index.ts"
  }
}
console.error, no console.log

El servidor usa console.error para logs porque el transporte stdio usa stdin/stdout para la comunicación con el cliente. Si usas console.log, interferiras con los mensajes del protocolo.

Con esto tienes un servidor MCP funcional que expone dos Tools y un Resource. Veamos como conectarlo.

Conectar a Claude Desktop

Claude Desktop soporta servidores MCP de forma nativa. Para registrar tu servidor, edita el archivo de configuración.

En macOS, el archivo esta en:

Ruta del archivo

En Windows:

Ruta del archivo

Agrega tu servidor a la configuración:

json
{
  "mcpServers": {
    "mi-servidor-usuarios": {
      "command": "npx",
      "args": ["tsx", "/ruta/absoluta/a/mi-servidor-mcp/src/index.ts"]
    }
  }
}

Reinicia Claude Desktop. Vas a ver un icono de herramientas en la ventana de chat que indica que tus Tools estan disponibles. Ahora puedes escribir algo como "busca al usuario con email ana@mail.com" y Claude va a usar tu servidor para obtener la información.

Usa rutas absolutas

La configuración de Claude Desktop requiere rutas absolutas al archivo de tu servidor. Las rutas relativas no funcionan porque Claude Desktop ejecuta el comando desde su propio directorio de trabajo.

Si quieres probar tu servidor antes de conectarlo a Claude Desktop, puedes usar el MCP Inspector -- una herramienta oficial que te permite interactuar con tu servidor directamente desde el navegador:

Terminal
$ npx @modelcontextprotocol/inspector tsx src/index.ts

Esto abre una interfaz web donde puedes ver los Tools y Resources registrados, ejecutarlos manualmente y ver las respuestas.

MCP + Vercel AI SDK

Si construyes aplicaciones con Next.js y Vercel AI SDK, puedes conectar servidores MCP directamente a tus agentes. AI SDK incluye soporte nativo para consumir Tools expuestos por servidores MCP.

typescript
// lib/mcp-client.ts
import { experimental_createMCPClient as createMCPClient } from "ai";
 
// Crear cliente MCP que se conecta a tu servidor
export async function crearClienteMCP() {
  const client = await createMCPClient({
    transport: {
      type: "sse",
      url: "http://localhost:3001/mcp",
    },
  });
 
  return client;
}
typescript
// app/api/chat/route.ts
import { generateText } from "ai";
import { anthropic } from "@ai-sdk/anthropic";
import { crearClienteMCP } from "@/lib/mcp-client";
 
export async function POST(req: Request) {
  const { messages } = await req.json();
 
  // Conectar al servidor MCP
  const mcpClient = await crearClienteMCP();
 
  // Obtener las herramientas del servidor MCP
  const toolsMCP = await mcpClient.tools();
 
  // Usar las herramientas en la generación de texto
  const resultado = await generateText({
    model: anthropic("claude-sonnet-4-20250514"),
    messages,
    tools: toolsMCP,
    maxSteps: 5,
  });
 
  // Cerrar la conexión al terminar
  await mcpClient.close();
 
  return new Response(JSON.stringify(resultado), {
    headers: { "Content-Type": "application/json" },
  });
}
AI SDK + MCP

AI SDK traduce automáticamente los Tools de MCP al formato que necesita el modelo que estes usando. No importa si usas Claude, GPT o Gemini -- los Tools funcionan igual porque AI SDK maneja la conversion internamente.

Para que esto funcione, tu servidor MCP necesita usar transporte SSE en lugar de stdio. Vamos a ver la diferencia.

Tipos de transporte: stdio vs SSE

MCP soporta dos formas de comunicación entre cliente y servidor.

stdio (Standard Input/Output)

El servidor corre como proceso hijo del cliente. La comunicación va por stdin/stdout.

typescript
// Servidor con transporte stdio
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
 
const transport = new StdioServerTransport();
await server.connect(transport);

cuándo usar stdio:

  • Servidores locales que corren en tu maquina
  • Integraciones con Claude Desktop, Cursor y editores de código
  • Herramientas de desarrollo y scripts personales
  • Cuando no necesitas acceso remoto

La ventaja de stdio es la simplicidad. No necesitas manejar autenticación, CORS ni puertos. El cliente inicia el proceso del servidor y se comunican directamente.

SSE (Server-Sent Events)

El servidor corre como endpoint HTTP. Los clientes se conectan via red.

typescript
// Servidor con transporte SSE
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
import express from "express";
 
const app = express();
 
// Mapa para rastrear las conexiones activas
const transports = new Map<string, SSEServerTransport>();
 
// Endpoint SSE para la conexión persistente
app.get("/mcp", (req, res) => {
  const transport = new SSEServerTransport("/mcp/message", res);
  const sessionId = transport.sessionId;
  transports.set(sessionId, transport);
 
  // Conectar el servidor MCP al transporte
  server.connect(transport);
 
  // Limpiar al cerrar la conexión
  req.on("close", () => {
    transports.delete(sessionId);
  });
});
 
// Endpoint para recibir mensajes del cliente
app.post("/mcp/message", (req, res) => {
  const sessionId = req.query.sessionId as string;
  const transport = transports.get(sessionId);
 
  if (transport) {
    transport.handlePostMessage(req, res);
  } else {
    res.status(404).json({ error: "sesión no encontrada" });
  }
});
 
app.listen(3001, () => {
  console.log("Servidor MCP escuchando en puerto 3001");
});

cuándo usar SSE:

  • Servidores que necesitan ser accesibles por red
  • Aplicaciones web que consumen MCP desde el backend
  • Cuando múltiples clientes necesitan conectarse al mismo servidor
  • Integraciones con AI SDK en aplicaciones Next.js
Streamable HTTP: el futuro del transporte MCP

La especificación MCP también define un transporte más nuevo llamado Streamable HTTP, que combina las ventajas de SSE con mejor soporte para conexiones stateless. Si estas empezando, stdio y SSE cubren la mayoria de los casos.

Ejemplos del mundo real

Hasta aquí trabajamos con datos simulados. Estos son patrones que vas a encontrar en servidores MCP de producción.

Consultas a base de datos

typescript
// Tool que consulta una base de datos real
server.tool(
  "ejecutar_consulta",
  "Ejecuta una consulta SQL de solo lectura contra la base de datos",
  {
    consulta: z.string().describe("Consulta SQL SELECT a ejecutar"),
  },
  async ({ consulta }) => {
    // Validar que sea solo SELECT (nunca permitir INSERT/UPDATE/DELETE)
    const consultaLimpia = consulta.trim().toUpperCase();
    if (!consultaLimpia.startsWith("SELECT")) {
      return {
        content: [
          {
            type: "text",
            text: "Solo se permiten consultas SELECT por seguridad",
          },
        ],
      };
    }
 
    try {
      const resultado = await db.query(consulta);
      return {
        content: [
          {
            type: "text",
            text: JSON.stringify(resultado.rows, null, 2),
          },
        ],
      };
    } catch (error) {
      return {
        content: [
          {
            type: "text",
            text: `Error en la consulta: ${(error as Error).message}`,
          },
        ],
      };
    }
  }
);
Seguridad en Tools de base de datos

Si tu servidor MCP ejecuta consultas SQL, aplica todas las prácticas de seguridad en aplicaciones web: queries parametrizadas, validación de inputs, permisos minimos. Un Tool con acceso a la base de datos sin restricciones es un vector de ataque.

Integración con APIs externas

typescript
// Tool que consume una API REST
server.tool(
  "obtener_clima",
  "Obtiene el clima actual de una ciudad",
  {
    ciudad: z.string().describe("Nombre de la ciudad"),
    pais: z.string().optional().describe("código de pais ISO (ej: MX, CO, AR)"),
  },
  async ({ ciudad, pais }) => {
    const query = pais ? `${ciudad},${pais}` : ciudad;
    const url = `https://api.weatherapi.com/v1/current.json?key=${process.env.WEATHER_API_KEY}&q=${encodeURIComponent(query)}&lang=es`;
 
    try {
      const response = await fetch(url);
      if (!response.ok) {
        throw new Error(`API respondio con status ${response.status}`);
      }
 
      const data = await response.json();
      return {
        content: [
          {
            type: "text",
            text: JSON.stringify(
              {
                ubicación: data.location.name,
                temperatura: `${data.current.temp_c} grados C`,
                condición: data.current.condition.text,
                humedad: `${data.current.humidity}%`,
              },
              null,
              2
            ),
          },
        ],
      };
    } catch (error) {
      return {
        content: [
          {
            type: "text",
            text: `Error al obtener el clima: ${(error as Error).message}`,
          },
        ],
      };
    }
  }
);

Acceso al sistema de archivos

typescript
import { readdir, readFile, stat } from "fs/promises";
import { join, resolve } from "path";
 
// Directorio raiz permitido (nunca dar acceso a todo el sistema)
const DIRECTORIO_BASE = resolve("./proyecto");
 
// Tool para listar archivos de un directorio
server.tool(
  "listar_archivos",
  "Lista los archivos y carpetas en un directorio del proyecto",
  {
    ruta: z
      .string()
      .default(".")
      .describe("Ruta relativa dentro del proyecto"),
  },
  async ({ ruta }) => {
    const rutaCompleta = resolve(join(DIRECTORIO_BASE, ruta));
 
    // Validar que no salga del directorio base
    if (!rutaCompleta.startsWith(DIRECTORIO_BASE)) {
      return {
        content: [
          { type: "text", text: "Acceso denegado: ruta fuera del proyecto" },
        ],
      };
    }
 
    try {
      const archivos = await readdir(rutaCompleta, { withFileTypes: true });
      const lista = archivos.map((f) => ({
        nombre: f.name,
        tipo: f.isDirectory() ? "directorio" : "archivo",
      }));
 
      return {
        content: [{ type: "text", text: JSON.stringify(lista, null, 2) }],
      };
    } catch (error) {
      return {
        content: [
          { type: "text", text: `Error: ${(error as Error).message}` },
        ],
      };
    }
  }
);
 
// Tool para leer el contenido de un archivo
server.tool(
  "leer_archivo",
  "Lee el contenido de un archivo del proyecto",
  {
    ruta: z.string().describe("Ruta relativa del archivo dentro del proyecto"),
  },
  async ({ ruta }) => {
    const rutaCompleta = resolve(join(DIRECTORIO_BASE, ruta));
 
    if (!rutaCompleta.startsWith(DIRECTORIO_BASE)) {
      return {
        content: [
          { type: "text", text: "Acceso denegado: ruta fuera del proyecto" },
        ],
      };
    }
 
    try {
      const info = await stat(rutaCompleta);
      // Limitar tamaño de archivos que se pueden leer
      if (info.size > 100_000) {
        return {
          content: [
            {
              type: "text",
              text: "El archivo supera el límite de 100KB",
            },
          ],
        };
      }
 
      const contenido = await readFile(rutaCompleta, "utf-8");
      return {
        content: [{ type: "text", text: contenido }],
      };
    } catch (error) {
      return {
        content: [
          { type: "text", text: `Error: ${(error as Error).message}` },
        ],
      };
    }
  }
);

Nota como el ejemplo válida que la ruta no salga del directorio base. Este tipo de validación es crítica en cualquier Tool que acceda al sistema de archivos.

El ecosistema MCP

MCP no es solo un protocolo -- ya tiene un ecosistema activo. Estos recursos te van a servir para ir más alla de lo básico.

Servidores MCP oficiales y de la comunidad

El repositorio oficial de servidores MCP tiene implementaciones listas para usar con PostgreSQL, SQLite, GitHub, Google Drive, Slack, Puppeteer y muchos más. En lugar de escribir tu servidor desde cero, puedes usar uno existente o tomarlo como base.

Microsoft MCP for Beginners

Microsoft público un curriculo open source de MCP con lecciones estructuradas, ejemplos en múltiples lenguajes y ejercicios prácticos. Es un recurso solido si quieres profundizar en el protocolo.

MCP en Next.js 16

Next.js 16 incluye MCP DevTools integrados para debug de servidores MCP durante el desarrollo. Esto confirma que MCP no es una especificación de nicho -- los frameworks mainstream estan adoptandolo como parte de su tooling oficial.

Estructura recomendada para servidores MCP en producción

Cuando tu servidor crece más alla de un archivo, esta estructura funciona bien:

Estructura de archivos

Separar Tools en archivos individuales facilita el testing y el mantenimiento. Cada Tool es una función pura que recibe parámetros validados y retorna un resultado -- ideal para unit tests.

Si ya manejas tipos genéricos en TypeScript, puedes crear helpers tipados que abstraigan la estructura repetitiva de los Tools:

typescript
// lib/crear-tool.ts
import { z, ZodObject, ZodRawShape } from "zod";
 
// Helper para crear Tools con tipado completo
export function definirTool<T extends ZodRawShape>(config: {
  nombre: string;
  descripción: string;
  schema: T;
  handler: (params: z.infer<ZodObject<T>>) => Promise<string>;
}) {
  return config;
}
 
// Uso
const buscarUsuario = definirTool({
  nombre: "buscar_usuario",
  descripción: "Busca un usuario por email",
  schema: {
    email: z.string().email(),
  },
  handler: async ({ email }) => {
    const usuario = await db.query("SELECT * FROM usuarios WHERE email = $1", [email]);
    return JSON.stringify(usuario);
  },
});

Recursos adicionales

Preguntas frecuentes

¿Qué es MCP y quien lo creo?

MCP (Model Context Protocol) es un estandar abierto creado por Anthropic que define como los modelos de IA se comunican con herramientas externas, APIs y bases de datos. Fue donado a la Linux Foundation para garantizar su neutralidad. Ya fue adoptado por OpenAI, Google y Microsoft.

¿MCP solo funciona con Claude?

No. Aunque Anthropic lo creo, MCP es un protocolo abierto. Funciona con cualquier modelo que implemente el estandar: Claude, GPT, Gemini, Mistral, modelos locales. La gracia del protocolo es que escribes un servidor una vez y funciona con todos.

¿Cuál es la diferencia entre MCP y function calling?

Function calling es específico de cada proveedor. OpenAI tiene su formato de tools, Anthropic tiene el suyo. Si quieres que tu herramienta funcione con ambos, tienes que implementarla dos veces. MCP estandariza esa conexión: escribes un servidor MCP y cualquier cliente compatible lo puede usar, sin importar que modelo este detrás.

¿Necesito un servidor especial para correr MCP?

No. Un servidor MCP puede ser tan simple como un script de Node.js que expone funciones como Tools. Con transporte stdio, corre como proceso local -- no necesitas ni un puerto abierto. Con transporte SSE, necesitas un servidor HTTP básico (Express, Fastify, o similar).

¿cómo se relaciona MCP con Vercel AI SDK?

AI SDK incluye soporte nativo para consumir servidores MCP. Puedes conectar cualquier servidor MCP a tus agentes de AI SDK, y el SDK traduce automáticamente los Tools al formato que necesita el modelo que estes usando. Combinas el estandar universal de MCP con la interfaz de TypeScript de AI SDK.

#mcp#ia#typescript#apis#anthropic#claude

Preguntas frecuentes

¿Qué es MCP y quien lo creo?

MCP (Model Context Protocol) es un estandar abierto creado por Anthropic que define como los modelos de IA se comunican con herramientas externas, APIs y bases de datos. Ha sido adoptado por OpenAI, Google y Microsoft, y donado a la Linux Foundation.

¿MCP solo funciona con Claude?

No. Aunque Anthropic lo creo, MCP es un protocolo abierto que funciona con cualquier modelo: Claude, GPT, Gemini, Mistral, y cualquier otro que implemente el estandar.

¿Cuál es la diferencia entre MCP y function calling?

Function calling es específico de cada proveedor (OpenAI tools, Anthropic tools). MCP es un protocolo estandar que funciona igual sin importar el proveedor. Piensalo como la diferencia entre un cargador propietario y USB-C.

¿Necesito un servidor especial para correr MCP?

No. Un servidor MCP puede correr como proceso local (stdio) o como endpoint HTTP (SSE). Puede ser tan simple como un script de Node.js que expone funciones como herramientas MCP.

¿Cómo se relaciona MCP con Vercel AI SDK?

AI SDK 6 incluye soporte nativo para MCP. Puedes conectar servidores MCP directamente a tus agentes de AI SDK, combinando lo mejor de ambos: el estandar universal de MCP con la interfaz de TypeScript de AI SDK.