ADC

Tool-based rate limiting for MCP Gateway

MCP clients can trigger repeated tool calls (tools/call), which can overload backend MCP servers and degrade the overall experience. Traditional HTTP-level throttling is often too coarse because it cannot differentiate between MCP methods or tools. Customers need MCP-aware rate limiting that can apply limits by tool name and user identity.

NetScaler® provides MCP-aware, tool-based rate limiting to enforce limits on MCP tool/execution requests by parsing MCP JSON-RPC payloads and applying thresholds per user or globally per tool. NetScaler enforces these rate limits by extracting the tool name from the JSON-RPC request body and optionally combining it with the authenticated user identity. This enables granular control of MCP tool/execution rates while returning a protocol-compliant error message that MCP clients can parse.

Some of the benefits are:

  • Protect backend MCP servers from overload due to a large number of tool calls.
  • Apply different limits for different tools (tool-level control).
  • Support per-user limits for fairness and abuse prevention.
  • Support global limits for total load per tool across all users.
  • Return MCP-compatible JSON-RPC error responses (client-friendly).

Use cases

This feature can be used in the following scenarios:

  • Define a per-user tool call limit: Restrict how frequently each user can call a specific tool, for example search or create operations.
  • Define a global tool call limit: Limit the total number of tool calls across all users for a high-cost tool.
  • Define DoS protection: Block spikes of tools/call traffic while returning a parseable JSON-RPC error to clients.

Points to note

  • Payload verification: Ensure that traffic checking relies on application or JSON Content-Type headers to isolate MCP JSON-RPC payloads.
  • JSON path filtering: Use JSON path expressions to target and isolate tools or call methods before tracking limits, preventing unrelated methods from triggering rate limits.
  • Error response integrity: Always return JSON-RPC-compatible error payloads to prevent parsing issues on client applications.
  • Evaluation order: Always evaluate and bind per-user policy limits before global policy limits to enforce client fairness first.

Prerequisites

Ensure that the following requirements are met:

  • MCP Gateway is configured and receives MCP traffic.
  • User identity is available when using per-user rate limiting (AAA.USER.NAME).
  • Streaming selectors are enabled and available for extracting JSON fields from request bodies.
  • You have administrative access permissions to create stream selectors, limit identifiers, responder actions and policies, and bind these policies to the target load balancing virtual servers.

Limitations

  • Rate limiting is applied only to requests that match your configured policy condition (such as tools/call). Other MCP methods bypass throttling unless additional matching rules are explicitly written and bound.
  • Per-user rate limiting requires a reliable user identity (AAA.USER.NAME). If a user identity is not available, use global rate limiting or an alternative identity source.

Configure rate limiting by using the CLI

  1. Create a responder action to rate-limit responses (JSON-RPC).

    Create a responder action that returns an MCP-compatible JSON-RPC error response. This preserves the JSON-RPC version and ID from the incoming request.

    add responder action mcp_ratelimit_resact respondwith q<"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{\"jsonrpc\":\"" + http.req.body(100000).xpath_json(xp%/jsonrpc%) + "\",\"id\":" + http.req.body(100000).xpath_json(xp%/id%) + ",\"result\": {\"isError\": true, \"content\":[{\"type\":\"text\",\"text\":\"Error: You have hit the rate limit. Please try again later.\"}]}}">
    <!--NeedCopy-->
    
  2. Configure a per-user tool rate limiting.

    Configure a per-user rate limiting that applies a limit per tool name per user. The selector extracts the tool name from params/name and combines it with AAA.USER.NAME.

    add stream selector mcp_tool_per_user_sel "HTTP.REQ.BODY(100000).XPATH_JSON(xp%/params/name%)" AAA.USER.NAME
    add ns limitIdentifier mcp_tool_per_user_limid -timeSlice 120000 -selectorName mcp_tool_per_user_sel
    
    add responder policy mcp_tool_per_user_respol "http.req.header(\"Content-Type\").EQ(\"application/json\") && http.req.body(100000).xpath_json(xp%boolean(//method)%) && http.req.body(100000).xpath_json(xp%/method%).eq(\"tools/call\") && sys.check_limit(\"mcp_tool_per_user_limid\")" mcp_ratelimit_resact
    <!--NeedCopy-->
    
  3. Configure a global tool rate limiting.

    Configure a global rate limiting that applies a limit per tool name across all users. The selector extracts only the tool name from params/name.

    add stream selector mcp_tool_global_sel "HTTP.REQ.BODY(100000).XPATH_JSON(xp%/params/name%)"
    add ns limitIdentifier mcp_tool_global_limid -timeSlice 120000 -selectorName mcp_tool_global_sel
    
    add responder policy mcp_tool_global_respol "http.req.header(\"Content-Type\").EQ(\"application/json\") && http.req.body(100000).xpath_json(xp%boolean(//method)%) && http.req.body(100000).xpath_json(xp%/method%).eq(\"tools/call\") && sys.check_limit(\"mcp_tool_global_limid\")" mcp_ratelimit_resact
    <!--NeedCopy-->
    
  4. Bind policies to the load balancing virtual server.

    Bind the per-user policy first, then the global policy. The per-user policy uses NEXT so the global policy can still apply when needed. The global policy uses END to stop further processing once the global limit is reached.

    bind lb vserver lb_app1_mcp -policyName mcp_tool_per_user_respol -priority 10 -gotoPriorityExpression NEXT -type REQUEST
    bind lb vserver lb_app1_mcp -policyName mcp_tool_global_respol -priority 20 -gotoPriorityExpression END -type REQUEST
    <!--NeedCopy-->
    

Note:

Tool-based rate-limiting behavior becomes active by default for matching requests as soon as you apply these policy bindings to your load balancing virtual servers. No separate global command or feature toggle is required.

Troubleshooting

Rate limiting not triggering

Verify that Content-Type is application/json and that the JSON-RPC method equals tools/call.

Per-user limit not working

Verify AAA.USER.NAME is populated for the request and AAA authentication is in place.

Unexpected responses

Confirm the responder action returns a JSON-RPC payload and preserves jsonrpc and id fields.

Order issues

Confirm that per-user policy priority is lower (evaluated first) than global policy and goto expressions are set as intended.

Tool-based rate limiting for MCP Gateway