MCP agent filters

Let agents request only the part of a response they need, with a JSONata expression per call.

Allow agent filters adds an optional response_filter parameter to every tool - the agent sends a JSONata expression with the call, the expression runs on the server and the agent receives only what it asked for.

A tool that lists invoices returns a many-row document - with a filter, the agent receives only the ids or the total it needs. The expression runs on the server, so the model spends no tokens on the rest.

Automatic discovery

Agent filters require no code changes anywhere:

  • With the toggle on, tools/list advertises response_filter on every tool's input schema, described as an optional JSONata expression applied to the response before it is returned - agents discover the parameter from the schema alone.
  • The major models already know JSONata and write the expressions themselves - an agent asked for totals alone sends a matching filter with the call.
  • Services stay unchanged and never see the parameter - it belongs to the gateway and is taken out of the arguments before argument validation runs.
  • Clients stay unchanged too - the parameter is never required, and a client that ignores it keeps receiving full responses as before.

Enable agent filters

  1. Go to AI > MCP gateways and click Edit on the gateway
  2. Check Allow agent filters
  3. Click OK

In enmasse, the gateway attribute is allow_agent_filters.

The expressions

JSONata is a query and transformation language for JSON. Given this tool response:

{
  "count": 5,
  "invoices": [
    {"invoice_id": "INV-2026-0001", "total": 101},
    {"invoice_id": "INV-2026-0002", "total": 102},
    {"invoice_id": "INV-2026-0003", "total": 103},
    {"invoice_id": "INV-2026-0004", "total": 104},
    {"invoice_id": "INV-2026-0005", "total": 105}
  ]
}

Each response_filter below runs against this document and produces the result next to it:

ExpressionWhat the agent receives
invoices.total[101, 102, 103, 104, 105]
invoices[total > 103].invoice_id["INV-2026-0004", "INV-2026-0005"]
$sum(invoices.total)515
{"first": invoices[0].invoice_id, "how_many": count}{"first": "INV-2026-0001", "how_many": 5}

A projection, a predicate, an aggregation and an object the agent composed itself - each call of one session can include a different expression, and a call without one receives the full response. Everything JSONata offers is available, jsonata.org documents the full language.

Order of application

Filters run after the response controls safeguards, so an expression runs on cleaned data - anything PII removal or the prompt-injection defenses took out is gone before the expression runs. Filters run before the token cap, so the cap measures the size of what goes out. With the audit log on, each applied expression is recorded verbatim in the event's data, under the agent_filter key.

Errors and edge cases

  • An expression with a syntax error, or one that fails against this document, is refused with an invalid-params error naming response_filter - agents correct the expression or retry without it.
  • A filter that matches nothing answers with a JSON null - the defined no-match shape.
  • Expressions are capped at 10,000 characters.
  • Errors are never filtered - a result with isError passes through untouched, exactly as the tool produced it.
  • A gateway with Allow agent filters off rejects the parameter as unknown, the way any other undeclared argument is rejected.

See also

FeatureWhat it does
Response controlsThe safeguards that clean data before a filter runs
Argument validationHow undeclared arguments are rejected
Audit logWhere each applied expression is recorded
MCP gatewaysConfiguration, endpoint behavior and the governance controls

Learn more