Skip to main content
Glama

json_filter

Filter JSON data from files or URLs using a shape object to extract specific fields and reduce context size for LLM processing.

Instructions

Filter JSON data using a shape object to extract only the fields you want. Provide filePath (local file or HTTP/HTTPS URL) and shape parameters.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
filePathYesPath to the JSON file (local) or HTTP/HTTPS URL to filter
shapeNoShape object (formatted as valid JSON) defining what fields to extract. Use 'true' to include a field, or nested objects for deep extraction. Examples: 1. Extract single field: {"type": true} 2. Extract multiple fields: {"type": true, "version": true, "source": true} 3. Extract nested fields: {"appState": {"gridSize": true, "viewBackgroundColor": true}} 4. Extract from arrays: {"elements": {"type": true, "x": true, "y": true}} - applies to each array item 5. Complex nested extraction: { "type": true, "version": true, "appState": { "gridSize": true, "viewBackgroundColor": true }, "elements": { "type": true, "text": true, "x": true, "y": true, "boundElements": { "type": true, "id": true } } } Note: - Arrays are automatically handled - the shape is applied to each item in the array. - Use json_schema tool to analyse the JSON file schema before using this tool. - Use json_dry_run tool to get a size breakdown of your desired json shape before using this tool.
chunkIndexNoIndex of chunk to retrieve (0-based). If filtered data exceeds 400KB, it will be automatically chunked. Defaults to 0 if not specified.

Implementation Reference

  • Core handler function that ingests JSON from file or URL, parses it, applies shape-based extraction, performs size check and automatic line-based chunking if exceeds 400KB threshold.
    async function processJsonFilter(input: JsonFilterInput): Promise<JsonFilterResult> {
      try {
        // Use strategy pattern to ingest JSON content
        const ingestionResult = await jsonIngestionContext.ingest(input.filePath);
        
        if (!ingestionResult.success) {
          // Map strategy errors to existing error format for backward compatibility
          return {
            success: false,
            error: ingestionResult.error
          };
        }
    
        // Parse JSON
        let parsedData: any;
        try {
          parsedData = JSON.parse(ingestionResult.content);
        } catch (error) {
          return {
            success: false,
            error: {
              type: 'invalid_json',
              message: 'Invalid JSON format in content',
              details: error
            }
          };
        }
    
        // Apply shape filter
        try {
          const filteredData = extractWithShape(parsedData, input.shape);
          
          // Convert filtered data to JSON string to check size
          const filteredJson = JSON.stringify(filteredData, null, 2);
          const filteredSize = new TextEncoder().encode(filteredJson).length;
          
          // Define chunking threshold (400KB)
          const CHUNK_THRESHOLD = 400 * 1024;
          
          // If under threshold, return all data
          if (filteredSize <= CHUNK_THRESHOLD) {
            return {
              success: true,
              filteredData
            };
          }
          
          // Calculate total chunks needed
          const totalChunks = Math.ceil(filteredSize / CHUNK_THRESHOLD);
          const chunkIndex = input.chunkIndex ?? 0; // Default to 0
          
          // Validate chunk index
          if (chunkIndex >= totalChunks || chunkIndex < 0) {
            return {
              success: false,
              error: {
                type: 'validation_error',
                message: `Invalid chunkIndex ${chunkIndex}. Must be between 0 and ${totalChunks - 1}`,
                details: { chunkIndex, totalChunks }
              }
            };
          }
          
          // Line-based chunking
          const lines = filteredJson.split('\n');
          const linesPerChunk = Math.ceil(lines.length / totalChunks);
          const startLine = chunkIndex * linesPerChunk;
          const endLine = Math.min(startLine + linesPerChunk, lines.length);
          
          // Extract chunk as text
          const chunkText = lines.slice(startLine, endLine).join('\n');
          
          return {
            success: true,
            filteredData: chunkText, // Return as string when chunking
            chunkInfo: {
              chunkIndex,
              totalChunks
            }
          };
        } catch (error) {
          return {
            success: false,
            error: {
              type: 'validation_error',
              message: 'Failed to apply shape filter',
              details: error
            }
          };
        }
      } catch (error) {
        return {
          success: false,
          error: {
            type: 'validation_error',
            message: 'Unexpected error during processing',
            details: error
          }
        };
      }
    }
  • src/index.ts:563-681 (registration)
    MCP server registration of the 'json_filter' tool, including detailed description, Zod input schema, and wrapper handler that handles shape parsing, validation, execution via processJsonFilter, and response formatting.
    server.tool(
        "json_filter",
        "Filter JSON data using a shape object to extract only the fields you want. Provide filePath (local file or HTTP/HTTPS URL) and shape parameters.",
        {
            filePath: z.string().describe("Path to the JSON file (local) or HTTP/HTTPS URL to filter"),
            shape: z.unknown().describe(`Shape object (formatted as valid JSON) defining what fields to extract. Use 'true' to include a field, or nested objects for deep extraction.
    
    Examples:
    1. Extract single field: {"type": true}
    2. Extract multiple fields: {"type": true, "version": true, "source": true}
    3. Extract nested fields: {"appState": {"gridSize": true, "viewBackgroundColor": true}}
    4. Extract from arrays: {"elements": {"type": true, "x": true, "y": true}} - applies to each array item
    5. Complex nested extraction: {
       "type": true,
       "version": true,
       "appState": {
         "gridSize": true,
         "viewBackgroundColor": true
       },
       "elements": {
         "type": true,
         "text": true,
         "x": true,
         "y": true,
         "boundElements": {
           "type": true,
           "id": true
         }
       }
    }
    
    Note: 
    - Arrays are automatically handled - the shape is applied to each item in the array.
    - Use json_schema tool to analyse the JSON file schema before using this tool.
    - Use json_dry_run tool to get a size breakdown of your desired json shape before using this tool.
    `),
            chunkIndex: z.number().optional().describe("Index of chunk to retrieve (0-based). If filtered data exceeds 400KB, it will be automatically chunked. Defaults to 0 if not specified.")
        },
        async ({ filePath, shape, chunkIndex }) => {
            try {
                // If shape is a string, parse it as JSON
                let parsedShape = shape;
                if (typeof shape === 'string') {
                    try {
                        parsedShape = JSON.parse(shape);
                    } catch (e) {
                        return {
                            content: [
                                {
                                    type: "text",
                                    text: `Error: Invalid JSON in shape parameter: ${e instanceof Error ? e.message : String(e)}`
                                }
                            ],
                            isError: true
                        };
                    }
                }
    
                
    
                const validatedInput = JsonFilterInputSchema.parse({
                    filePath,
                    shape: parsedShape,
                    chunkIndex
                });
                
                const result = await processJsonFilter(validatedInput);
                
                if (result.success) {
                    // Check if chunking is active
                    if (result.chunkInfo) {
                        // Return chunk data + metadata as separate content items
                        return {
                            content: [
                                {
                                    type: "text",
                                    text: result.filteredData // This is already a string when chunking
                                },
                                {
                                    type: "text",
                                    text: JSON.stringify(result.chunkInfo)
                                }
                            ]
                        };
                    } else {
                        // No chunking - return as normal JSON
                        return {
                            content: [
                                {
                                    type: "text",
                                    text: JSON.stringify(result.filteredData, null, 2)
                                }
                            ]
                        };
                    }
                } else {
                    return {
                        content: [
                            {
                                type: "text",
                                text: `Error: ${result.error.message}`
                            }
                        ],
                        isError: true
                    };
                }
            } catch (error) {
                return {
                    content: [
                        {
                            type: "text",
                            text: `Validation error: ${error instanceof Error ? error.message : String(error)}`
                        }
                    ],
                    isError: true
                };
            }
        }
    );
  • Zod input validation schema used internally by the json_filter handler for filePath, shape, and optional chunkIndex.
    const JsonFilterInputSchema = z.object({
      filePath: z.string().min(1, "File path or HTTP/HTTPS URL is required").refine(
        (val) => val.length > 0 && (val.startsWith('./') || val.startsWith('/') || val.startsWith('http://') || val.startsWith('https://') || !val.includes('/')),
        "Must be a valid file path or HTTP/HTTPS URL"
      ),
      shape: z.any().describe("Shape object defining what to extract"),
      chunkIndex: z.number().int().min(0).optional().describe("Index of chunk to retrieve (0-based)")
    });
  • Recursive helper function that applies the shape filter to JSON data or arrays, extracting only specified fields and nested structures.
    function extractWithShape(data: any, shape: Shape): any {
      if (Array.isArray(data)) {
        return data.map(item => extractWithShape(item, shape));
      }
    
      const result: any = {};
      for (const key in shape) {
        const rule = shape[key];
        if (rule === true) {
          result[key] = data[key];
        } else if (typeof rule === 'object' && data[key] !== undefined) {
          result[key] = extractWithShape(data[key], rule);
        }
      }
      return result;
    }
  • TypeScript type definition for the output of processJsonFilter, including success case with filteredData and optional chunkInfo, or error.
    type JsonFilterResult = {
      readonly success: true;
      readonly filteredData: any;
      readonly chunkInfo?: {
        readonly chunkIndex: number;
        readonly totalChunks: number;
      };
    } | {
      readonly success: false;
      readonly error: JsonSchemaError;
    };
Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/kehvinbehvin/json-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server