1. Por qué hace falta un inspector de MCP
Imagina que estás depurando el frontend, pero te prohíben abrir DevTools. Así es, más o menos, la vida sin un inspector de MCP. El protocolo MCP va «debajo del capó» de ChatGPT y del Apps SDK; si solo miras la respuesta en el chat y piensas: «¿Por qué no ve mi herramienta?», en esencia estás disparando a ciegas.
Inspectores como MCP Inspector (oficial) o MCP Jam son clientes MCP para desarrolladores. Pueden:
- conectarse a tu servidor MCP igual que lo hace ChatGPT;
- realizar el handshake y leer las capabilities;
- solicitar la lista de tools/resources/prompts;
- invocar cualquier tool manualmente con argumentos arbitrarios;
- mostrar mensajes JSON en bruto (requests / replies / errors).
En esencia, es «un Postman para MCP, pero con cerebro». A diferencia de un cliente REST normal, el inspector conoce las particularidades de MCP: entiende tools/list, tools/call, sabe mostrar los esquemas de argumentos e incluso a veces admite flujos OAuth para servidores protegidos.
Si no tienes un inspector, la depuración se ve así: abres ChatGPT, intentas llamar a una App, ves «Error talking to app» o que la herramienta ni siquiera se invoca, y empiezas a preguntarte: ¿la modelo no quiso llamar al tool, tu MCP no arrancó o es un error de JSON? Con el inspector puedes verificar cada capa por separado: primero el servidor MCP a solas con el inspector y, después, el vínculo ChatGPT ↔ MCP.
2. Mini‑resumen de inspectores: MCP Inspector, Jam y compañía
En la práctica, usarás dos tipos de inspectores para MCP con más frecuencia.
En primer lugar, está el MCP Inspector oficial del repositorio de Model Context Protocol. Es una aplicación web (normalmente un SPA en React) que se levanta localmente o vía npx/Docker y puede conectarse a tu servidor MCP por HTTP/SSE.
En segundo lugar, existen inspectores del estilo MCP Jam, que a menudo añaden comodidades para OAuth. Pueden leer por sí mismos .well-known/oauth-protected-resource, extraer de ahí authorization_endpoint y token_endpoint, completar el flujo PKCE y, ya en estado autorizado, llamar al MCP.
MCP Jam fue creado por desarrolladores sobre la base de MCP Inspector. Si MCP Inspector implementa el conjunto mínimo de herramientas de depuración, MCP Jam implementa todo lo que puede necesitar un desarrollador en su trabajo diario con MCP. Personalmente recomiendo usar MCP Jam desde el principio para no tener que reaprender después.
Para nuestro curso, la diferencia es:
- el Inspector básico te sirve siempre, incluso para el servidor MCP más sencillo y sin protección;
- MCP Jam (o análogo) es útil cuando llegues a los módulos de autenticación y autorización.
Pero la idea general es la misma: es un cliente MCP normal, solo que sabe mostrar con claridad lo que ChatGPT hace «en silencio».
3. Flujo típico de trabajo con un inspector de MCP
Recorramos un flujo típico: has escrito un tool nuevo en tu servidor MCP y quieres asegurarte de que realmente funciona.
En la lección anterior ya levantaste un servidor MCP mínimo. Ahora añadiremos un enfoque sistemático de verificación: ejecutaremos el ciclo completo «servidor → inspector → lógica JSON» paso a paso.
Paso 1 — arrancar el servidor MCP
Ya lo hiciste en la lección anterior: supongamos que tienes un script npm run mcp-dev:
# ejemplo de inicio del servidor MCP
npm run mcp-dev
# bajo el capó algo como: ts-node src/mcp-server.ts
Es importante que el servidor escuche el transporte que elijas: en el curso suele ser el endpoint HTTP /mcp en algún puerto, por ejemplo http://localhost:4001/mcp.
Paso 2 — arrancar MCP Jam
Segunda terminal:
# una de las formas de iniciar MCP Jam
npx @mcpjam/inspector@latest
# si es necesario, puedes añadir --port 4002, etc.
Después, el inspector se abre en el navegador, normalmente en http://localhost:6274 o en un puerto similar.
En la pantalla de inicio de MCP Jam te pedirán la URL del servidor MCP. Introduces:
http://localhost:4001/mcp
o tu URL tunelizada, si ya estás usando algo como ngrok.
Paso 3 — handshake / capabilities
En cuanto MCP Jam se conecta, hace automáticamente lo mismo que hace ChatGPT:
- Envía la solicitud de inicialización (initialize) con los datos del cliente.
- Recibe la respuesta con la versión del protocolo y las capabilities de tu servidor.
- Con base en las capabilities entiende si el servidor admite tools, resources, prompts y otras funciones.
En la UI suele mostrarse algo como:
Connected
Protocol: mcp/2025-06-18
Capabilities:
- tools: list, call
- resources: list, read
- prompts: list, get
Si ya en este paso el inspector no puede conectarse (connection refused, CORS, 500, etc.), ves inmediatamente el error y entiendes: el problema seguro no está en la modelo ni en ChatGPT, sino en tu parte de servidor o en la red.
Paso 4 — discovery: ver tools/resources/prompts
Tras un handshake correcto, el inspector suele invocar por sí mismo métodos como tools/list, resources/list, prompts/list para rellenar la barra lateral. Verás:
- una lista de herramientas con descripciones y el JSON Schema de sus argumentos de entrada;
- una lista de recursos agrupados por colecciones/rutas;
- una lista de prompts con descripciones breves.
Si acabas de añadir un tool nuevo pero no aparece en la lista, significa que no está registrado correctamente en el servidor o que el servidor no se levantó con el código actualizado. Es mucho más fácil detectarlo aquí que intentar adivinar por qué ChatGPT «no quiere» llamar a tu herramienta.
4. Llamada manual de tools con MCP Jam
La función más útil de MCP Jam es la invocación manual de herramientas. Es tu UI personal para tools/call.
Elegir una herramienta y rellenar los argumentos
Supongamos que en el módulo anterior escribiste el tool suggest_gifts:
// en algún lugar de src/mcp/tools/suggestGifts.ts
export const suggestGiftsTool = {
name: "suggest_gifts",
description: "Propone ideas de regalos según la edad, el presupuesto y los intereses",
inputSchema: {
type: "object",
properties: {
age: { type: "number" },
budget: { type: "number" },
interests: {
type: "array",
items: { type: "string" }
}
},
required: ["age", "budget"]
},
// handler se define por separado
};
En MCP Jam haces clic en suggest_gifts. A la derecha se abre un formulario, generado a partir de inputSchema. Allí rellenas:
{
"age": 30,
"budget": 100,
"interests": ["juegos", "libros"]
}
y pulsas «Call» o un botón similar.
El inspector envía la solicitud MCP tools/call y verás al momento:
- los datos JSON en bruto de la solicitud (exactamente lo que sale hacia el servidor);
- los datos JSON en bruto de la respuesta (result o error);
- posiblemente, una vista previa más cómoda del resultado.
Leer los registros JSON en el inspector
Normalmente el inspector muestra algo como:
// Request
{
"id": "1",
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "suggest_gifts",
"arguments": {
"age": 30,
"budget": 100,
"interests": ["juegos", "libros"]
}
}
}
// Reply
{
"id": "1",
"jsonrpc": "2.0",
"result": {
"content": [
{
"type": "text",
"text": "1) Juego de mesa ... 2) Tarjeta regalo para una librería ..."
}
]
}
}
Si tu handler lanza una excepción, verás un error al estilo JSON‑RPC:
{
"id": "1",
"jsonrpc": "2.0",
"error": {
"code": -32603,
"message": "Internal error",
"data": "TypeError: Cannot read properties of undefined ..."
}
}
Muy importante: aquí estás viendo el nivel de protocolo. Si la respuesta no tiene el formato que esperan el Apps SDK/ChatGPT, podrás detectarlo antes de empezar a culpar a «bugs de GPT».
5. Depuración de recursos y prompts
Los tools no son todo lo que puede hacer MCP. Ya sabes que también existen resources y prompts.
Con el inspector puedes:
- abrir la lista de recursos (resources/list) y ver sus metadatos;
- leer un recurso concreto (resources/read) y comprobar que los datos devueltos son correctos;
- realizar búsquedas sobre los recursos (si implementaste esa posibilidad);
- ver los prompts predefinidos y su texto.
Por ejemplo, si tienes un recurso gift_catalog:
// pseudocódigo de registro del recurso
registerResource({
uri: "resource://giftgenius/catalog",
name: "Catálogo de regalos",
mimeType: "application/json",
handler: async () => {
return JSON.stringify(giftCatalogData);
}
});
En el inspector verás este recurso, harás clic en él y podrás ver el JSON de inmediato. Si resulta que el JSON no es válido o que el tipo MIME es extraño, lo detectarás antes de que ChatGPT empiece a tropezar al intentar leerlo o incrustarlo en un widget.
6. Registros del servidor MCP: qué, dónde y cómo registrar
MCP Jam está muy bien, pero no basta: necesitas los registros del propio servidor MCP. Sin ellos, cualquier producción se convierte en una lotería.
Qué registrar
Mínimo útil:
- cada mensaje MCP entrante (request/notification) con:
- hora;
- método (tools/call, tools/list, etc.);
- nombre del tool (si aplica);
- argumentos truncados (sin datos sensibles);
- cada respuesta saliente:
- estado (éxito / error);
- tiempo de ejecución;
- versión abreviada del resultado o al menos su tipo;
- errores técnicos:
- parseo de JSON;
- excepciones inesperadas en los handlers.
Y es muy importante no registrar PII ni secretos completos: tokens, contraseñas, textos completos de solicitudes confidenciales. Las recomendaciones de logging en producción suelen indicar registrar datos con PII truncada.
Dónde escribir los registros: stdout / stderr
MCP tiene un requisito importante: los mensajes JSON deben ir por el «canal correcto», y todos los logs de depuración por otro. Por ejemplo, si usas un transporte sobre stdout/stderr, entonces:
- los mensajes JSON‑RPC deben ir por stdout;
- todos los console.log, console.error, etc., deben dirigirse a stderr.
Si mezclas JSON y logs de texto en el mismo flujo, el cliente (MCP Jam o ChatGPT) no podrá parsear los mensajes, porque entre los JSON aparecerá de repente una cadena como Server started at http://localhost:4001. Este es uno de los errores más frecuentes en servidores MCP.
En escenarios HTTP el problema es más leve, pero el principio es el mismo: la respuesta HTTP debe ser JSON puro, y todos los logs deben ir a la consola/archivo, pero no al cuerpo de la respuesta.
Un logger sencillo para un servidor MCP en TypeScript
Añadamos a nuestro servidor MCP de ejemplo un pequeño logger:
// src/logger.ts
export function logRequest(method: string, details: unknown) {
console.error(
JSON.stringify({
level: "info",
type: "request",
method,
details,
ts: new Date().toISOString(),
})
);
}
export function logError(method: string, error: unknown) {
console.error(
JSON.stringify({
level: "error",
type: "error",
method,
error: String(error),
ts: new Date().toISOString(),
})
);
}
Y en el handler de tools:
// src/mcp-server.ts (fragmento)
server.setRequestHandler("tools/call", async (req) => {
logRequest("tools/call", {
name: req.params?.name,
// aquí es mejor no incluir todo el payload, sino solo campos seguros
});
try {
const result = await handleToolCall(req);
return result;
} catch (e) {
logError("tools/call", e);
throw e;
}
});
Así verás en la consola registros JSON estructurados, que luego es fácil correlacionar entre sí por ts o por un requestId adicional.
7. Conjunto: MCP Jam + registros
La estrategia correcta para depurar MCP casi siempre es:
- Reproducir el problema en el inspector: ves que tools/list devuelve una lista vacía, tools/call falla, la respuesta JSON es extraña, etc.
- Al mismo tiempo mirar los registros del servidor MCP: qué escribe al arrancar, qué errores muestra en cada mensaje, si hay stack trace.
- Correlacionar id, method, ts en los logs con lo que ve el inspector.
Por ejemplo, ves en el inspector:
{
"error": {
"code": -32603,
"message": "Internal error"
}
}
Y en paralelo, en los registros:
{
"level": "error",
"type": "error",
"method": "tools/call",
"error": "TypeError: Cannot read properties of undefined (reading 'age')",
"ts": "2025-11-21T10:15:12.345Z"
}
Listo, diagnóstico claro: en algún lugar del handler esperas age, pero el esquema/argumentos son otros.
8. Mini checklist: ¿está listo el servidor MCP para integrarse con la App?
Antes de conectar el servidor MCP a una ChatGPT App real, conviene pasar un pequeño checklist con el inspector.
En primer lugar, el handshake y las capabilities deben completarse sin errores. MCP Jam debe mostrar que el servidor admite las entidades que necesitas: al menos tools y, si se usan, resources / prompts.
En segundo lugar, la lista de tools/resources/prompts en el inspector debe coincidir con el conjunto de herramientas, recursos y prompts que das por implementado. Erratas en name, registros olvidados, etc., se detectan aquí al instante.
En tercer lugar, las invocaciones de tools con argumentos válidos deben devolver de forma estable un result correcto. Idealmente, prueba varios casos típicos (solicitudes en las que realmente confías en producción).
En cuarto lugar, las invocaciones con argumentos no válidos deben devolver respuestas de error claras al estilo JSON‑RPC, y no caer con un 500. Por ejemplo, si falta un parámetro obligatorio, conviene devolver un error estructurado que luego ChatGPT pueda convertir en un mensaje comprensible para el usuario.
En quinto lugar, los registros del servidor no deberían inundar la consola con gigabytes de stack trace por cualquier nimiedad. Los errores deben estar estructurados y los datos sensibles, filtrados con cuidado.
Si todo esto se cumple en el inspector, puedes conectar el servidor MCP al Apps SDK con mucha más tranquilidad y empezar a jugar con los widgets en Dev Mode.
9. Errores típicos del servidor MCP y cómo cazarlos con el inspector
Ahora pasemos a lo más jugoso: qué se rompe con mayor frecuencia y cómo verlo.
Configuración y conexión
A veces parece que «el servidor no funciona», y el problema es que ni siquiera escucha el puerto o el endpoint adecuados. El inspector, en ese caso, dirá claramente connection refused o ni siquiera podrá conectarse. Causas frecuentes: URL incorrecta (por ejemplo, /mcp en lugar de /api/mcp), puerto ocupado por otro proceso, túnel no levantado o CORS bloqueando las solicitudes.
JSON no válido / mezcla de logs y protocolo
Uno de los casos más dolorosos es cuando imprimes console.log("Server started") en stdout, y por encima de eso deben ir los mensajes JSON‑RPC. El cliente espera JSON puro, pero recibe texto + JSON, intenta parsearlo y falla por error de formato.
La solución es sencilla: separar estrictamente qué va al flujo del protocolo (stdout o cuerpo de la respuesta HTTP) y qué va a los logs (stderr o un archivo aparte).
Desajuste entre el esquema y la implementación del tool
Otro error habitual: en inputSchema declaras una cosa y en el código esperas otra. Por ejemplo, el esquema dice que age es un número y interests es un array opcional de strings, pero el código intenta hacer arguments.interests.toLowerCase(). La modelo (y el inspector) envían interests como null o ni siquiera mandan el campo, y todo se cae.
El inspector permite ver explícitamente qué JSON se envía realmente en tools/call y compararlo con tu código.
Nombres incorrectos de tools/resources
Si en capabilities / tools/list exportas un tool como suggest_gifts_v2, y en el manifiesto del App o en el widget esperas suggest_gifts, «tool no encontrado» te acompañará hasta el final del proyecto. En el inspector, por la lista de tools y sus campos name, esto se ve de inmediato, sin intentar adivinar qué piensa GPT.
Tools lentos o que se quedan colgados
Si la llamada a un tool en el inspector tarda 30 segundos y luego cae por timeout, no esperes que ChatGPT reaccione mejor. El inspector MCP te ayudará a entender en qué etapa te estás atascando: llamada de red, base de datos, API externa. En los logs conviene tener el tiempo de inicio y fin del procesamiento de cada solicitud para ver los outliers al instante.
10. Errores comunes al inspeccionar y depurar MCP
Error n.º 1: intentar depurar MCP solo a través de ChatGPT.
Muchos desarrolladores primero conectan MCP a la App, ven que «algo no funciona» y empiezan a cambiar prompts, descripciones del tool e incluso la versión del modelo. Mientras tanto, el servidor MCP ni arranca o tools/list está vacío. Empieza siempre por el inspector: si allí todo va mal, el modelo no tiene la culpa.
Error n.º 2: mezclar JSON‑RPC y logs en el mismo flujo.
Cuando el cliente MCP espera JSON puro y tú imprimes en stdout cadenas de depuración, el resultado es previsible: el parseo se rompe, Inspector muestra errores extraños. Los logs deben ir aparte (stderr, archivos, sistemas externos de logging), y los mensajes del protocolo, estrictamente por su canal.
Error n.º 3: no fijarse en las capabilities y la lista de tools.
A menudo una herramienta «desaparece» simplemente porque olvidaste registrarla o habilitar la capability correspondiente. Si no miras capabilities y tools/list en el inspector, puedes pasar mucho tiempo creyendo que la culpa es del modelo y no de tu código de registro.
Error n.º 4: ignorar errores de esquema y desajustes de JSON.
Cuando inputSchema y el JSON real no coinciden, la modelo y el inspector comienzan a comportarse de forma extraña, como es lógico. Si no miras los mensajes JSON en bruto en el inspector y no validas el esquema, estos errores aparecerán en los lugares más inesperados.
Error n.º 5: registrar todo, incluyendo PII y tokens.
En el fragor de la depuración es fácil imprimir en los logs el cuerpo completo de la solicitud, incluyendo posibles datos personales o secretos. En producción esto es una bomba de relojería: fugas, problemas de compliance, etc. Registra solo lo necesario para el diagnóstico y con datos truncados/anonimizados.
Error n.º 6: no reproducir el problema con casos mínimos.
A veces un bug aparece en un diálogo complejo a través de ChatGPT y el desarrollador intenta depurarlo tal cual. Es mucho más eficaz reproducir el mismo escenario en el inspector con una o dos solicitudes MCP, eliminando la influencia de los prompts, el historial del diálogo y el «humor» del modelo.
GO TO FULL VERSION