> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getmcp.com/llms.txt
> Use this file to discover all available pages before exploring further.

# JMESPath Response Pruning

> Use JMESPath expressions to extract and filter API responses, cutting AI token costs before they reach the model.

## Overview

When a tool calls an external API, the raw response is often large — paginated lists with dozens of fields, nested objects, metadata the AI never needs. GetMCP's **response pruning** lets you extract only the relevant data before the response is sent to the AI client.

Two query engines are available:

| Engine                 | Best for                                                       |
| ---------------------- | -------------------------------------------------------------- |
| **JSONPath** (default) | Simple field extraction, dot-notation paths                    |
| **JMESPath**           | Filtering, projections, multi-field selection, computed values |

JMESPath is the recommended engine for any response that involves **filtering** or **reshaping** data — it can reduce a 50 KB API response to a few hundred bytes before the AI ever sees it.

***

## Why This Matters: Token Costs

AI models bill by token. A token is roughly 4 characters of text. Every byte in an API response that reaches the AI is a byte you're paying for — and a byte consuming limited context-window space.

**Example: a WooCommerce orders list**

|                                                    | Bytes     | Approx. tokens     | Cost at \$3/M tokens |
| -------------------------------------------------- | --------- | ------------------ | -------------------- |
| Raw upstream response (100 orders)                 | \~800 KB  | \~200,000          | \$0.60 per call      |
| After JMESPath pruning (`[*].{id, status, total}`) | \~4 KB    | \~1,000            | \$0.003 per call     |
| **Savings**                                        | **99.5%** | **199,000 tokens** | **\$0.597 per call** |

At 500 tool calls per day, that's **\~\$300/day saved** from one JMESPath expression.

Beyond cost, smaller payloads:

* Fit more tool results in a single AI context window
* Reduce hallucination risk (the AI focuses on fewer fields)
* Make session replay and logs far more readable

***

## Where to Configure It

Open **GetMCP → Servers → \{Your Server} → Tools → \{Tool} → Edit**.

In the **Response Mapping** section:

1. Set **Selector Type** to `jmespath`.
2. Enter your JMESPath expression in the **Selector** field.
3. Click **Test** to see the pruned output live.

<img src="https://mintlify.s3.us-west-1.amazonaws.com/infiwebs/images/jmespath-response-mapping.png" alt="Tool Editor — Response Mapping section with JMESPath engine selected and expression field" />

***

## JMESPath Syntax Quick Reference

JMESPath expressions operate on the decoded JSON body of the API response.

### Extract a field

```jmespath theme={null}
data.items
```

Extracts the `items` array from `{ "data": { "items": [...] } }`.

### Project specific fields from an array

```jmespath theme={null}
items[*].{id: id, name: name, price: price}
```

Turns an array of full product objects into an array of `{id, name, price}` objects — everything else is dropped.

### Filter an array

```jmespath theme={null}
orders[?status == 'pending']
```

Returns only orders where `status` equals `"pending"`.

### Filter and project

```jmespath theme={null}
orders[?status == 'pending'].{id: id, customer: customer.name, total: total_amount}
```

Combines filtering and projection — only pending orders, only three fields each.

### Nested access

```jmespath theme={null}
response.data.user.profile.email
```

Walks any depth of nesting.

### Sort and slice

```jmespath theme={null}
sort_by(products, &price)[:10]
```

Returns the 10 cheapest products sorted by price ascending.

### Flatten a nested list

```jmespath theme={null}
results[].tags[]
```

Flattens `[{tags: [...]}, {tags: [...]}]` into a single flat tag list.

***

## Practical Examples

### WooCommerce: orders list

Raw response from `/wp-json/wc/v3/orders` is \~8 KB per order. Pruning extracts only what the AI needs:

```jmespath theme={null}
[*].{id: id, status: status, total: total, customer_email: billing.email, date: date_created}
```

Result: \~150 bytes per order instead of 8 KB — a **50× reduction**.

### Mailchimp: campaign stats

```jmespath theme={null}
campaigns[*].{id: id, subject: settings.subject_line, opens: report_summary.opens, clicks: report_summary.clicks}
```

### OpenWeather API: current conditions only

```jmespath theme={null}
{temp: main.temp, feels_like: main.feels_like, description: weather[0].description, city: name}
```

### GitHub: PR list — only open ones

```jmespath theme={null}
[?state == 'open'].{number: number, title: title, author: user.login, created: created_at}
```

***

## Live Testing

Use the **Test** button in the Tool Editor to call the real API and see both the full raw response and the pruned output side by side. The test result panel shows:

* **Pruned response** — exactly what the AI client will receive
* **Raw response** — the full upstream body for debugging

<img src="https://mintlify.s3.us-west-1.amazonaws.com/infiwebs/images/jmespath-test-result.png" alt="JMESPath test result panel showing pruned output alongside raw response with byte counts" />

***

## Token Savings Dashboard

Every live tool call records the upstream byte count (raw) and the delivered byte count (after pruning). The **Interceptor Savings** widget on the Analytics page shows the aggregate savings across all calls, so you can see the real-world impact of your JMESPath expressions.

<img src="https://mintlify.s3.us-west-1.amazonaws.com/infiwebs/images/interceptor-savings-widget.png" alt="Analytics page — Interceptor Savings widget showing upstream bytes, saved bytes, and delivered bytes" />

***

## How Pruning Fits in the Processing Pipeline

Every tool call passes through this sequence before the AI sees the result:

```
Upstream API response
        │
        ▼
1. JMESPath / JSONPath pruning   ← prune first
        │
        ▼
2. PII redaction                 ← runs on already-pruned data
        │
        ▼
3. Template formatting           ← applied to cleaned, pruned output
        │
        ▼
   AI client (Claude, Cursor, …)
```

**JMESPath runs first** — which is important for two reasons:

1. **PII redaction is faster.** The redactor only regex-scans the fields that survived pruning. If you've already stripped 49 of 50 fields with JMESPath, the PII engine has 98% less text to process.
2. **PII placeholders land correctly.** Template substitution sees `[REDACTED:EMAIL]` as a label rather than a raw email address, so the AI still understands something was present.

### Using Pruning and PII Redaction Together

This is the recommended combination for any tool that touches customer or personal data:

* **JMESPath** removes fields the AI doesn't need (cost savings + focus)
* **PII Redaction** scrubs sensitive values from the fields the AI *does* see (compliance + safety)

**Example — CRM contact lookup:**

```jmespath theme={null}
contacts[*].{id: id, name: full_name, email: email, plan: subscription.plan}
```

This prunes the contact object from 40+ fields to 4. Then PII redaction replaces the actual email addresses with `[REDACTED:EMAIL]` before the AI sees them. The AI knows a contact has an email field, but never sees the address.

Configure PII redaction under **Server Settings → PII Redaction**. See the [PII Redaction guide](/docs/guides/pii-redaction) for details.

***

## Fallback Behaviour

| Situation                       | What happens                                                                 |
| ------------------------------- | ---------------------------------------------------------------------------- |
| JMESPath library not installed  | Returns full unfiltered response; an error is logged to `debug.log`          |
| Expression syntax error         | Returns full unfiltered response; error logged with the offending expression |
| Expression returns `null`       | `null` is returned to the AI as a JSON `null` value                          |
| Response body is not valid JSON | JMESPath is skipped; raw body returned as a text block                       |

***

## JSONPath vs JMESPath

| Feature                    | JSONPath                                            | JMESPath                             |
| -------------------------- | --------------------------------------------------- | ------------------------------------ |
| Simple field access        | ✓                                                   | ✓                                    |
| Dot-notation               | ✓                                                   | ✓                                    |
| Array slicing              | Limited                                             | ✓                                    |
| Filtering (`[?condition]`) | Limited                                             | ✓                                    |
| Multi-field projection     | ✗                                                   | ✓                                    |
| Sorting (`sort_by`)        | ✗                                                   | ✓                                    |
| Flattening (`[]`)          | ✗                                                   | ✓                                    |
| Spec / test suite          | [Goessner](https://goessner.net/articles/JsonPath/) | [jmespath.org](https://jmespath.org) |

Use JSONPath when migrating existing selectors written for it. Use JMESPath for any new tool that needs filtering or projection.
