This server exposes 23 tools via HTTP with basic Express routing. All tools have names starting with action verbs (getUser, createCourse, deleteCourse, etc.), which is good. However, the implementation suffers from CRITICAL gaps: (1) NO input schemas are visible in the source code, the tool definitions are inferred from route handlers, not explicitly registered with JSON Schema. (2) Descriptions are present but MINIMAL, most are 10 - 40 characters ('Obtener un usuario mediante correo electronico' = 42 chars), which barely meet the 10-char minimum and lack context for when/why an LLM should use the tool. (3) NO output schemas are documented anywhere. (4) NO error handling guidance, controllers return HTTP status codes and generic JSON, but no actionable recovery hints. (5) Several tools combine related concerns (e.g., forgotPassword + recoveryPassword could be a single flow; editPassword and editEmail are separate when they could be composed). (6) Tool definitions are NOT REGISTERED explicitly in an MCP tools capability, they appear to be plain Express routes, so the actual schema, input validation, and return types are inferred from inspection, not declared. Per the hard rules, inferred tools cap at 50, and tools without visible schemas cap their schema score at 0. Because this is an HTTP server that IS remotely callable (not STDIO), protocolReadiness is scored normally, but the lack of explicit MCP tool registration and schema visibility heavily penalizes definitionQuality.
Crear una nueva clase
Crear un nuevo curso
Eliminar una clase
Eliminar curso
Editar Clase
Editar curso
Cambiar correo electronico del usuario
Cambiar contraseña del usuario
NO explicit MCP tool registration with JSON Schema, all 23 tools are inferred from Express route handlers. No visible input schema definitions, output schemas, or structured parameter validation in the source.
Descriptions are universally minimal (25 - 40 characters). Examples: 'Obtener un usuario mediante correo electronico' (42 chars) lacks context for when/why to call vs alternatives; 'Obtener datos del usuario autenticado' (36 chars) does not explain what fields are returned or how it differs from getUser. Baseline for A-tier is 50 - 200 chars with actionable context.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | F | 31 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 0 | - | v1 |
Cambiar usuario, nombre y apellido
Editar el rol de un usuario
Olvide mi contraseña - envía código de verificación al correo
Obtener lista de clases de un curso
Obtener lista de cursos
Obtener datos del usuario autenticado
Obtener la cantidad de usuarios FREE/PREMIUM
Obtener un usuario mediante correo electronico
Inicio de sesión del usuario
Marcar una clase como vista
Verificación de usuario y cambio de contraseña
Registro de usuario
Reenviar código de verificación
Actualizar el orden de las clases
Verificación de usuario
NO output schemas documented. Controllers return Express responses (200 OK with JSON body), but there is no declaration of what fields, types, and structure an LLM can expect. E.g., getCourses returns a list, but is it [course_id, title] or [id, name, description, level, imageUrl, ...]? LLMs cannot plan downstream tool chains without knowing what data is available.
NO error handling guidance. All error paths return HTTP status codes (401, 403, 404, 500) with generic messages ('No autorizado', 'Hubo un error'). Per pattern, errors should tell the LLM what to do next. E.g., 'User not found (404). Try register() first if the account doesn't exist.' instead of a bare 401.
Parameter descriptions are missing for MANY inputs. E.g., 'role' in editUserRole accepts enum ['ADMIN','PREMIUM','FREE'] but no description explains what each role grants. 'verification_code' in verify has a brief desc, but no mention of format, TTL, or retry limits. 'classOrders' in updateClassOrder is described as 'Array of objects...' but lacks field-by-field breakdown.
Destructive operations (deleteCourse, deleteClass) have NO confirmation or dry-run pattern. An LLM could call deleteCourse(id=123) on the first attempt to satisfy a vague user request like 'remove the math course', permanently deleting data. No idempotency guarantee either.
JWT token is passed in the request body (req.body.token populated by auth middleware), not in standard Authorization header. LLMs and tool frameworks expect Bearer tokens in Authorization; custom body injection is non-standard and error-prone.
Two password recovery tools (forgotPassword + recoveryPassword) should be a single multi-step flow or clearly separated as discovery vs action. LLMs may call both in wrong order, or forget the middle step (check email for code). No guidance in tool descriptions.
No pagination on list endpoints. getCourses() and getClasses() return all results with no limit/offset or total count. If a course has 1000 classes, returning all as JSON will blow context window and waste tokens.
Tool names are good (verb_noun format), but some could be more precise. E.g., 'editProfile' changes name, last_name, and username, three separate concerns. 'editPassword' and 'editEmail' are separate tools, which is good, but 'editProfile' bundles unrelated fields. Should be 'updateUserName' + 'updateUserEmail' + 'updateUserLastName' or a focused 'updateDisplayName'.