En modo aplicar MCP Shield responde él mismo a algunos mensajes. Esta página recoge cada respuesta, por qué tiene esa forma y el evento que deja. En modo registro no se envía ninguna: el mensaje pasa y solo queda el evento, con blocked: false.
Por qué casi todos los bloqueos son errores JSON-RPC
Los clientes MCP tratan un estado HTTP de error como un fallo del transporte: la llamada en curso falla, y algunos clientes tiran o reintentan la sesión entera. Un error JSON-RPC con el id de la petición se entrega en cambio a esa llamada concreta. El asistente enseña «blocked by OpenWAF MCP Shield: …» en esa llamada a la herramienta y la sesión sigue funcionando.
Por eso los bloqueos de política y de revisión responden HTTP 200 con un error JSON-RPC. Solo se usa un estado HTTP de error cuando no hay id de petición al que responder (un cuerpo que no se puede leer) o cuando el problema es el cliente entero (ritmo y tamaño).
Todas las respuestas
| Situación (aplicar) | HTTP | Código JSON-RPC | Tipo de evento | Id de detección |
|---|---|---|---|---|
Más de rate_per_token peticiones por minuto | 429 con Retry-After | -32000 | mcp_rate_limited | mcp.rate_limited |
Cuerpo de más de max_request_kb | 413 | -32600 | mcp_invalid | mcp.too_large |
| El cuerpo no es JSON | 400, id null | -32700 | mcp_invalid | mcp.parse_error |
| JSON pero no JSON-RPC 2.0, o un lote vacío | 400, id null | -32600 | mcp_invalid | mcp.invalid_request |
Método fuera de methods_allowed | 200 | -32601 | mcp_blocked_method | mcp.method_not_allowed |
Herramienta en tools_denied, o ausente de un tools_allowed no vacío | 200 | -32602 | mcp_blocked_tool | mcp.tool_denied, mcp.tool_not_allowed |
Inyección o credencial en la petición, inspect_requests: block | 200 | -32001 | mcp_injection_request, mcp_dlp | Los ids de los detectores |
Inyección o credencial en la respuesta, inspect_responses: block | El de tu servidor | -32001, en lugar de ese mensaje de respuesta (mismo id; en un flujo, ese evento) | mcp_injection_response, mcp_dlp | Los ids de los detectores |
| Una notificación bloqueada | 202, sin cuerpo | — | mcp_blocked_method | mcp.method_not_allowed |
Las peticiones que el servidor manda al cliente (sampling/createMessage, elicitation/create) solo se anotan; nunca se sustituyen.
Qué recibe el cliente
El mensaje es blocked by OpenWAF MCP Shield: seguido de los ids de detección separados por comas. error.data.openwaf repite el tipo de evento y los ids, para que un cliente o un agente distinga un bloqueo del escudo de un error de tu servidor:
{"jsonrpc": "2.0", "id": 7,
"error": {"code": -32602, "message": "blocked by OpenWAF MCP Shield: mcp.tool_denied",
"data": {"openwaf": {"kind": "mcp_blocked_tool", "detections": ["mcp.tool_denied"]}}}}Un resultado de herramienta sustituido por una detección tiene la misma forma, con el código -32001, el id de la petición original y los ids de los detectores, por ejemplo blocked by OpenWAF MCP Shield: pi.override.en, exfil.markdown_image. El límite de ritmo responde -32000 con el mensaje rate limit exceeded (OpenWAF MCP Shield).
Lotes
Si se bloquea algún mensaje de un lote, el borde responde el lote entero y no llega nada a tu servidor. La respuesta es un array con 200: cada mensaje bloqueado lleva su error y cada una de las demás peticiones con id lleva -32600 batch rejected by OpenWAF MCP Shield. Un lote sin ids de petición (solo notificaciones) recibe 202.
Eventos
Cada mensaje bloqueado o con detecciones deja un evento entre los de Bots y agentes de IA, uno por tipo y mensaje (muestreados a como mucho 200 por sitio y minuto):
| Tipo | Cuándo |
|---|---|
mcp_blocked_method | Un método fuera de methods_allowed |
mcp_blocked_tool | Una herramienta denegada o no permitida |
mcp_injection_request | Un detector de inyección encontró algo en la petición |
mcp_injection_response | Un detector de inyección encontró algo en la respuesta |
mcp_dlp | Un patrón de credenciales encontró algo en la petición o en la respuesta |
mcp_rate_limited | Se pasó el límite por token |
mcp_invalid | El cuerpo era demasiado grande, no era JSON o no era JSON-RPC |
Cada evento lleva las detecciones (id, etiqueta y un fragmento de como mucho 160 bytes, redactado en las credenciales) y un objeto mcp:
| Campo | Qué es |
|---|---|
method | El método JSON-RPC, vacío si no se conoce (cuerpo no válido, flujo GET) |
tool | El nombre de la herramienta de tools/call, la URI de resources/read (recortada) o el nombre del prompt |
token_fp | Una huella de la cabecera Authorization: los 8 primeros bytes de su SHA-256, en hexadecimal. Nunca el token |
blocked | true si el borde respondió o sustituyó el mensaje, false si solo se anotó |
Cada uno es también un evento de seguridad con la regla MCP Shield, acción block o log, en la vista de eventos en directo y en Control de rastreadores IA → MCP Shield. Desde la CLI:
openwaf-cloud ctl ai report example.com --view events --kind mcp_injection_response,mcp_dlp --limit 50Contadores
Por endpoint, el informe cuenta las peticiones, los mensajes JSON-RPC del cliente, los mensajes bloqueados (respondidos con un error del escudo o respuestas sustituidas), los mensajes con al menos una detección de inyección o de credenciales y las respuestas que pasaron sin revisar (demasiado grandes o todavía comprimidas). Por herramienta, cuenta llamadas, bloqueos y detecciones, hasta 50 herramientas por endpoint; el resto se suma en *. Los datos se guardan 30 días.