The JSON Threat Protection Policy validates incoming requests with a JSON body against policy limits that you’ve configured, regardless of whether the Content-Type header exists or is set to application/json. If a request violates the policy limits, you can configure it to either block the request (block mode) or monitor and log it (tap mode).
The Policy validates the JSON body of incoming POST, PUT, and PATCH requests. Other HTTP methods aren’t validated.
The Policy checks the following limits:
- Maximum container depth of the entire JSON object.
- Maximum number of array elements.
- Maximum number of object entries.
- Maximum length of object keys.
- Maximum length of strings.
Additionally, you can set a policy that restricts the JSON body size (config.max_body_size). When this is configured, the Policy compares the Content-Length header with max_body_size. In block mode, if the Content-Length header is missing or its value exceeds max_body_size, the request is terminated. In tap mode, only the body size is checked and logs are recorded.
Notes:
- Length calculation for JSON strings and object entry names is based on UTF-8 characters, not bytes.
-
max_body_size and nginx_http_client_max_body_size are independent of each other. Therefore, if nginx_http_client_max_body_size is set to a larger value while max_body_size is smaller and block mode is enabled, any request with a body size greater than max_body_size but less than nginx_http_client_max_body_size is terminated.
- This Policy doesn’t support chunked encoding.
Consider an AI MCP Server that exposes a draw-cards tool, where deck_id is expected to be a short identifier returned by an earlier shuffle-cards call, such as t8952axdsfat. A well-behaved tools/call request looks like this:
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "draw-cards",
"arguments": {
"path_deck_id": "t8952axdsfat",
"query_count": 1
}
}
}
A client attempting to abuse the path_deck_id argument, for example to probe for buffer or parsing issues in an upstream integration, might substitute an oversized value instead:
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "draw-cards",
"arguments": {
"path_deck_id": "deck-id-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"query_count": 1
}
}
}
With config.max_string_value_length set to 40, the Policy rejects the second request with a 400 response, and logs an entry similar to:
[json-threat-protection] JSON validate failed: at [$.params.arguments.path_deck_id]: The maximum length allowed for a string value is exceeded.
The Policy checks every string, array, and object in the request body this way, regardless of which tool or argument name it appears under.
The MCP handshake itself has a fixed shape you don’t control. The initialize request’s params object always includes a protocolVersion key, which is 15 characters long. If config.max_object_entry_name_length is set below 16, the Policy rejects every initialize request and no client can complete the handshake.