# Filtering large MCP tool responses with jq
Source: https://speakeasy.com/mcp/tool-design/response-filtering-jq

Large API responses consume valuable LLM context. When an API returns hundreds of user records, the LLM must process every field of every record, even when only a few specific details are needed. This wastes context space and slows down response generation.

## The context window problem

Consider a contact management API. A tool that calls `GET /contacts` might return 100 contacts, each with 20 fields (name, email, phone, address, company, etc.). That's 2,000 fields of data loaded into the LLM's context, when the user might only need email addresses.

Traditional solutions involve manually filtering response data in the MCP server code. This creates a tradeoff: Either include all data (wasting context) or exclude fields (making data inaccessible when needed).

## What is jq?

jq is a lightweight command-line JSON processor. Like `sed` for JSON data, jq slices, filters, and transforms structured data with minimal syntax. It's particularly effective for extracting specific values from complex API responses.

## Dynamic response filtering in MCP

Response filtering allows the LLM to apply jq syntax to transform API responses based on the response schema. The LLM dynamically selects only the information needed to answer each query.

## Implementation with FastMCP

Here's how to implement jq filtering in a FastMCP tool:

```python
import subprocess
import json
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("Contact Manager")

@mcp.tool()
def get_contacts(jq_filter: str | None = None) -> str:
    """Retrieve contact information.

    Args:
        jq_filter: Optional jq syntax to filter the response
    """
    # Fetch contacts from your API
    response = fetch_contacts_from_api()

    # Apply jq filter if provided
    if jq_filter:
        response = apply_jq_filter(response, jq_filter)

    return json.dumps(response)

def apply_jq_filter(data: dict, filter_expr: str) -> dict:
    """Apply a jq filter to JSON data."""
    try:
        # Convert data to JSON string
        json_input = json.dumps(data)

        # Run jq command
        result = subprocess.run(
            ['jq', filter_expr],
            input=json_input,
            capture_output=True,
            text=True,
            check=True
        )

        return json.loads(result.stdout)
    except subprocess.CalledProcessError as e:
        return {"error": f"Invalid jq filter: {e.stderr}"}
    except json.JSONDecodeError:
        return {"error": "Failed to parse jq output"}
```

With this implementation, the LLM can apply jq filters dynamically:

```python