MCP (Model Context Protocol): Guia para Conectar IA con tus APIs
Aprende que es MCP, como funciona y como 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): Guia 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 integracion tres veces. MCP estandariza esa conexion 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 especificacion teorica -- es el protocolo que usan Claude Desktop, Cursor, Windsurf y decenas de herramientas en produccion.
En este tutorial vas a entender como funciona MCP, construir tu primer servidor con TypeScript, conectarlo a Claude Desktop y usarlo con Vercel AI SDK en una aplicacion Next.js.
El problema que resuelve MCP
Sin MCP, conectar un modelo de IA a tus herramientas se ve asi:
// 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 mas
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 documentacion 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 conexion entre modelos de IA y herramientas externas.
Como funciona MCP: arquitectura
La arquitectura de MCP tiene tres capas:
Host (aplicacion de IA)
|
+-- Client (maneja la conexion)
|
+-- 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 aplicacion 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 conexion con el servidor MCP. Maneja el ciclo de vida de la comunicacion.
- Server: un proceso que expone herramientas, recursos y prompts al modelo a traves del protocolo MCP. Puede ser un script local o un endpoint HTTP.
Un Host, multiples 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 comunicacion 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 mas usado. Son funciones que el modelo puede decidir llamar basandose en el contexto de la conversacion. Piensa en ellas como function calling, pero estandarizado.
// 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 logica -- simplemente proveen informacion que el modelo puede usar como contexto.
// 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 configuracion 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 utiles para estandarizar interacciones comunes.
// Ejemplo conceptual de un Prompt
{
name: "revisar_codigo",
description: "Analiza codigo y sugiere mejoras",
arguments: [
{ name: "lenguaje", description: "Lenguaje de programacion", required: true },
{ name: "codigo", description: "Codigo a revisar", required: true }
]
}En la practica, los Tools son la funcionalidad que mas vas a usar. Los Resources son utiles cuando tu servidor maneja datos que el modelo necesita consultar frecuentemente. Los Prompts son mas de nicho.
Configuracion del proyecto
Vamos a crear un servidor MCP desde cero con TypeScript. Lo primero es preparar el proyecto.
$ mkdir mi-servidor-mcp && cd mi-servidor-mcp && npm init -yInstala el SDK oficial de MCP y las dependencias necesarias:
$ npm install @modelcontextprotocol/sdk zod$ npm install -D typescript @types/node tsxConfigura TypeScript:
// 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 asi:
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.
// 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 direccion 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 especifico",
{
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 ejecucion en tu package.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 comunicacion 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 configuracion.
En macOS, el archivo esta en:
En Windows:
Agrega tu servidor a la configuracion:
{
"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 informacion.
Usa rutas absolutas
La configuracion 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:
$ npx @modelcontextprotocol/inspector tsx src/index.tsEsto 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.
// 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;
}// 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 generacion de texto
const resultado = await generateText({
model: anthropic("claude-sonnet-4-20250514"),
messages,
tools: toolsMCP,
maxSteps: 5,
});
// Cerrar la conexion al terminar
await mcpClient.close();
return new Response(JSON.stringify(resultado), {
headers: { "Content-Type": "application/json" },
});
}AI SDK + MCP
AI SDK traduce automaticamente 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 comunicacion entre cliente y servidor.
stdio (Standard Input/Output)
El servidor corre como proceso hijo del cliente. La comunicacion va por stdin/stdout.
// Servidor con transporte stdio
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
const transport = new StdioServerTransport();
await server.connect(transport);Cuando usar stdio:
- Servidores locales que corren en tu maquina
- Integraciones con Claude Desktop, Cursor y editores de codigo
- Herramientas de desarrollo y scripts personales
- Cuando no necesitas acceso remoto
La ventaja de stdio es la simplicidad. No necesitas manejar autenticacion, 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.
// 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 conexion 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 conexion
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: "Sesion no encontrada" });
}
});
app.listen(3001, () => {
console.log("Servidor MCP escuchando en puerto 3001");
});Cuando usar SSE:
- Servidores que necesitan ser accesibles por red
- Aplicaciones web que consumen MCP desde el backend
- Cuando multiples clientes necesitan conectarse al mismo servidor
- Integraciones con AI SDK en aplicaciones Next.js
Streamable HTTP: el futuro del transporte MCP
La especificacion MCP tambien define un transporte mas 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 aqui trabajamos con datos simulados. Estos son patrones que vas a encontrar en servidores MCP de produccion.
Consultas a base de datos
// 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 practicas de seguridad en aplicaciones web: queries parametrizadas, validacion de inputs, permisos minimos. Un Tool con acceso a la base de datos sin restricciones es un vector de ataque.
Integracion con APIs externas
// 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("Codigo 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(
{
ubicacion: data.location.name,
temperatura: `${data.current.temp_c} grados C`,
condicion: 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
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 tamano de archivos que se pueden leer
if (info.size > 100_000) {
return {
content: [
{
type: "text",
text: "El archivo supera el limite 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 valida que la ruta no salga del directorio base. Este tipo de validacion es critica 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 mas alla de lo basico.
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 mas. En lugar de escribir tu servidor desde cero, puedes usar uno existente o tomarlo como base.
Microsoft MCP for Beginners
Microsoft publico un curriculo open source de MCP con lecciones estructuradas, ejemplos en multiples lenguajes y ejercicios practicos. 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 especificacion de nicho -- los frameworks mainstream estan adoptandolo como parte de su tooling oficial.
Estructura recomendada para servidores MCP en produccion
Cuando tu servidor crece mas alla de un archivo, esta estructura funciona bien:
Separar Tools en archivos individuales facilita el testing y el mantenimiento. Cada Tool es una funcion pura que recibe parametros validados y retorna un resultado -- ideal para unit tests.
Si ya manejas tipos genericos en TypeScript, puedes crear helpers tipados que abstraigan la estructura repetitiva de los Tools:
// 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;
descripcion: string;
schema: T;
handler: (params: z.infer<ZodObject<T>>) => Promise<string>;
}) {
return config;
}
// Uso
const buscarUsuario = definirTool({
nombre: "buscar_usuario",
descripcion: "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
- Documentacion oficial de MCP -- la especificacion completa del protocolo, guias de inicio rapido y referencia de la API.
- Repositorio oficial de servidores MCP -- servidores listos para usar con bases de datos, APIs y servicios populares.
- Microsoft MCP for Beginners -- curriculo estructurado con lecciones y ejercicios.
- Documentacion de MCP en Anthropic -- guias especificas para la integracion con Claude.
Preguntas frecuentes
Que 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.
Cual es la diferencia entre MCP y function calling?
Function calling es especifico 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 conexion: escribes un servidor MCP y cualquier cliente compatible lo puede usar, sin importar que modelo este detras.
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 basico (Express, Fastify, o similar).
Como 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 automaticamente 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.
Preguntas frecuentes
Que 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.
Cual es la diferencia entre MCP y function calling?
Function calling es especifico 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.
Como 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.
Articulos relacionados
Zod Avanzado: Discriminated Unions, Transforms y Pipes
Patrones avanzados de Zod: discriminated unions, transforms, pipes, preprocess, y como validar datos complejos en TypeScript con schemas reutilizables.
tRPC + Next.js: APIs Type-Safe sin REST
Implementa tRPC en Next.js para APIs 100% type-safe. Sin schemas de API, sin fetch manual, sin types duplicados. End-to-end type safety con TypeScript.
Webhooks en Next.js: Recibe y Procesa Eventos
Implementa webhooks en Next.js para recibir eventos de Stripe, GitHub, Clerk y otros servicios. Verificacion de firmas, tipado y manejo de errores.