Skip to main content
Glama
ricleedo

JSON MCP Boilerplate

by ricleedo

json_extract

Extract specific data from JSON files using paths, filters, patterns, or slices. Retrieve particular values, filter arrays/objects by conditions, search for patterns, or slice data for targeted extraction and analysis.

Instructions

Extract specific data using paths, filters, patterns, or slices from JSON files. Always use this tool when you need to retrieve particular values, filter arrays/objects by conditions, search for patterns, or slice data. Ideal for targeted data extraction, data transformation, and focused analysis of specific JSON elements.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
file_pathYesPath to the JSON file
pathNoDot notation path to target
filterNoJS condition to filter results (e.g., 'item.age > 18')
patternNoRegex pattern to search for
search_typeNoWhat to search when using pattern
startNoArray slice start index
endNoArray slice end index
keysNoSpecific object keys to extract
default_valueNoFallback if path not found

Implementation Reference

  • The async handler function implementing the core logic of the 'json_extract' tool. Loads JSON file, extracts by path using getValueByPath, applies filter using filterObject, performs regex pattern search recursively, slices arrays if indices provided, extracts specific keys from objects, truncates large results, formats as pretty JSON, handles errors.
    async ({ file_path, path, filter, pattern, search_type, start, end, keys, default_value, }) => { try { const data = readJSONFile(file_path); let target = path ? getValueByPath(data, path) : data; // If path was specified but not found, return default value if (path && target === undefined) { const output = default_value !== undefined ? default_value : null; return { content: [ { type: "text", text: JSON.stringify( { result: output, message: `Path not found: ${path}, returning default value`, }, null, 2 ), }, ], }; } // Apply filter if specified if (filter) { target = filterObject(target, filter); } // Apply pattern search if specified if (pattern) { const results: any[] = []; const flags = "gi"; // Case-insensitive by default const regex = new RegExp(pattern, flags); const searchFor = search_type || "both"; function searchObject(obj: any, currentPath: string = ""): void { if (Array.isArray(obj)) { obj.forEach((item, index) => { searchObject(item, `${currentPath}[${index}]`); }); } else if (typeof obj === "object" && obj !== null) { Object.entries(obj).forEach(([key, value]) => { const newPath = currentPath ? `${currentPath}.${key}` : key; if ( (searchFor === "key" || searchFor === "both") && regex.test(key) ) { results.push({ type: "key", path: newPath, key, value }); } if (searchFor === "value" || searchFor === "both") { if (value === null && pattern === "null") { results.push({ type: "value", path: newPath, key, value }); } else if (typeof value === "string" && regex.test(value)) { results.push({ type: "value", path: newPath, key, value }); } else if ( typeof value === "number" && regex.test(value.toString()) ) { results.push({ type: "value", path: newPath, key, value }); } else if ( typeof value === "boolean" && regex.test(value.toString()) ) { results.push({ type: "value", path: newPath, key, value }); } } searchObject(value, newPath); }); } } searchObject(target); target = results; } // Apply slicing if specified if ((start !== undefined || end !== undefined) && Array.isArray(target)) { const sliceStart = start || 0; const sliceEnd = end || target.length; target = target.slice(sliceStart, sliceEnd); } // Extract specific keys if specified if ( keys && typeof target === "object" && target !== null && !Array.isArray(target) ) { const extracted: any = {}; keys.forEach((key) => { if (key in target) { extracted[key] = target[key]; } }); target = extracted; } const truncatedTarget = truncateForOutput(target); let outputText = JSON.stringify(truncatedTarget, null, 2); // Replace quoted truncation messages with unquoted text for markdown-like output outputText = outputText.replace( /"\.\.\.(\d+) more items"/g, "...$1 more items" ); outputText = outputText.replace( /"\.\.\.(\d+) more properties": "\.\.\.?"/g, "...$1 more properties" ); return { content: [{ type: "text", text: outputText }], }; } catch (error: any) { return { content: [{ type: "text", text: `Error: ${error.message}` }], }; } }
  • Zod input schema defining parameters for json_extract: file_path (required), optional path, filter (JS condition), pattern (regex), search_type (key/value/both), start/end (array slice), keys (array of strings), default_value.
    file_path: z.string().describe("Path to the JSON file"), path: z.string().optional().describe("Dot notation path to target"), filter: z .string() .optional() .describe("JS condition to filter results (e.g., 'item.age > 18')"), pattern: z.string().optional().describe("Regex pattern to search for"), search_type: z .enum(["key", "value", "both"]) .optional() .describe("What to search when using pattern"), start: z.number().optional().describe("Array slice start index"), end: z.number().optional().describe("Array slice end index"), keys: z .array(z.string()) .optional() .describe("Specific object keys to extract"), default_value: z.any().optional().describe("Fallback if path not found"), },
  • src/index.ts:298-456 (registration)
    Registers the 'json_extract' tool on the MCP server using server.tool(), providing name, long description, input schema, and inline async handler function.
    server.tool( "json_extract", "Extract specific data using paths, filters, patterns, or slices from JSON files. Always use this tool when you need to retrieve particular values, filter arrays/objects by conditions, search for patterns, or slice data. Ideal for targeted data extraction, data transformation, and focused analysis of specific JSON elements.", { file_path: z.string().describe("Path to the JSON file"), path: z.string().optional().describe("Dot notation path to target"), filter: z .string() .optional() .describe("JS condition to filter results (e.g., 'item.age > 18')"), pattern: z.string().optional().describe("Regex pattern to search for"), search_type: z .enum(["key", "value", "both"]) .optional() .describe("What to search when using pattern"), start: z.number().optional().describe("Array slice start index"), end: z.number().optional().describe("Array slice end index"), keys: z .array(z.string()) .optional() .describe("Specific object keys to extract"), default_value: z.any().optional().describe("Fallback if path not found"), }, async ({ file_path, path, filter, pattern, search_type, start, end, keys, default_value, }) => { try { const data = readJSONFile(file_path); let target = path ? getValueByPath(data, path) : data; // If path was specified but not found, return default value if (path && target === undefined) { const output = default_value !== undefined ? default_value : null; return { content: [ { type: "text", text: JSON.stringify( { result: output, message: `Path not found: ${path}, returning default value`, }, null, 2 ), }, ], }; } // Apply filter if specified if (filter) { target = filterObject(target, filter); } // Apply pattern search if specified if (pattern) { const results: any[] = []; const flags = "gi"; // Case-insensitive by default const regex = new RegExp(pattern, flags); const searchFor = search_type || "both"; function searchObject(obj: any, currentPath: string = ""): void { if (Array.isArray(obj)) { obj.forEach((item, index) => { searchObject(item, `${currentPath}[${index}]`); }); } else if (typeof obj === "object" && obj !== null) { Object.entries(obj).forEach(([key, value]) => { const newPath = currentPath ? `${currentPath}.${key}` : key; if ( (searchFor === "key" || searchFor === "both") && regex.test(key) ) { results.push({ type: "key", path: newPath, key, value }); } if (searchFor === "value" || searchFor === "both") { if (value === null && pattern === "null") { results.push({ type: "value", path: newPath, key, value }); } else if (typeof value === "string" && regex.test(value)) { results.push({ type: "value", path: newPath, key, value }); } else if ( typeof value === "number" && regex.test(value.toString()) ) { results.push({ type: "value", path: newPath, key, value }); } else if ( typeof value === "boolean" && regex.test(value.toString()) ) { results.push({ type: "value", path: newPath, key, value }); } } searchObject(value, newPath); }); } } searchObject(target); target = results; } // Apply slicing if specified if ((start !== undefined || end !== undefined) && Array.isArray(target)) { const sliceStart = start || 0; const sliceEnd = end || target.length; target = target.slice(sliceStart, sliceEnd); } // Extract specific keys if specified if ( keys && typeof target === "object" && target !== null && !Array.isArray(target) ) { const extracted: any = {}; keys.forEach((key) => { if (key in target) { extracted[key] = target[key]; } }); target = extracted; } const truncatedTarget = truncateForOutput(target); let outputText = JSON.stringify(truncatedTarget, null, 2); // Replace quoted truncation messages with unquoted text for markdown-like output outputText = outputText.replace( /"\.\.\.(\d+) more items"/g, "...$1 more items" ); outputText = outputText.replace( /"\.\.\.(\d+) more properties": "\.\.\.?"/g, "...$1 more properties" ); return { content: [{ type: "text", text: outputText }], }; } catch (error: any) { return { content: [{ type: "text", text: `Error: ${error.message}` }], }; } } );
  • getValueByPath: Recursive dot-notation path navigator used to extract target data from JSON object.
    function getValueByPath(obj: any, path: string): any { return path.split(".").reduce((current, key) => { if (current === null || current === undefined) return undefined; if (Array.isArray(current) && !isNaN(Number(key))) { return current[Number(key)]; } return current[key]; }, obj); }
  • filterObject: Applies user-provided JavaScript filter condition to arrays (item, index) or objects (value, key, index).
    function filterObject(obj: any, condition: string): any { try { // For arrays: item, index are available // For objects: value, key, index are available const conditionFn = new Function( "item", "key", "index", "value", `return ${condition}` ); if (Array.isArray(obj)) { return obj.filter((item, index) => conditionFn(item, undefined, index, item) ); } else if (typeof obj === "object" && obj !== null) { const result: any = {}; Object.entries(obj).forEach(([key, value], index) => { if (conditionFn(value, key, index, value)) { result[key] = value; } }); return result; } return obj; } catch (error: any) { throw new Error(`Invalid filter condition: ${error.message}`); } }
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/ricleedo/JSON-MCP-Boilerplate'

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