Skip to main content
Glama

query

Extract and manipulate JSON data by specifying a URL and JSONPath expression, enabling precise querying, filtering, sorting, and transformation of JSON content.

Instructions

Query JSON data using JSONPath syntax

Input Schema

NameRequiredDescriptionDefault
jsonPathYesJSONPath expression (e.g. $.store.book[*].author)
urlYesURL of the JSON data source

Input Schema (JSON Schema)

{ "properties": { "jsonPath": { "description": "JSONPath expression (e.g. $.store.book[*].author)", "type": "string" }, "url": { "description": "URL of the JSON data source", "type": "string" } }, "required": [ "url", "jsonPath" ], "type": "object" }

Implementation Reference

  • Main handler for the 'query' tool. Fetches JSON from URL, applies extended JSONPath query with support for filters, aggregations, sorting, grouping, transformations (numeric, string, date, array), projections, and returns formatted result.
    if (name === "query") { const { url, jsonPath } = QueryArgumentsSchema.parse(args); const jsonData = await fetchData(url); // Handle complex filtering with string operations const filterMatch = jsonPath.match(/\[\?\((.+?)\)\]/); if (filterMatch) { const condition = filterMatch[1]; let baseData = Array.isArray(jsonData) ? jsonData : [jsonData]; // Get the base path before the filter const basePath = jsonPath.split('[?')[0]; if (basePath !== '$') { baseData = JSONPath.value(jsonData, basePath); } // Apply filter let result = handleComplexFilter(baseData, condition); // Handle operations after filter const afterFilter = jsonPath.split(')]')[1]; if (afterFilter) { if (afterFilter.includes('.{')) { // Handle projection const projectionMatch = afterFilter.match(/\.\{(.+?)\}/); if (projectionMatch) { const fieldPairs = projectionMatch[1].split(',') .map(pair => { const [key, value] = pair.split(':').map(s => s.trim()); return { key, value: value || key }; }); result = result.map((item: Record<string, any>) => { const obj: Record<string, any> = {}; fieldPairs.forEach(({ key, value }) => { obj[key] = item[value]; }); return obj; }); } } } return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }], }; } // Handle numeric operations if (jsonPath.match(/\.(math|round|floor|ceil|abs|sqrt|pow2)/)) { let baseData; const basePath = jsonPath.split('.math')[0].split('.round')[0] .split('.floor')[0].split('.ceil')[0] .split('.abs')[0].split('.sqrt')[0].split('.pow2')[0]; if (basePath === '$') { baseData = Array.isArray(jsonData) ? jsonData : [jsonData]; } else { baseData = JSONPath.value(jsonData, basePath); if (!Array.isArray(baseData)) { baseData = [baseData]; } } const numericOp = jsonPath.slice(basePath.length); const result = handleNumericOperations(baseData, numericOp); return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }], }; } // Handle date operations if (jsonPath.match(/\.(format|isToday|add)\(/)) { const baseData = Array.isArray(jsonData) ? jsonData : [jsonData]; const dateOp = jsonPath.slice(jsonPath.indexOf('.')); const result = handleDateOperations(baseData, dateOp); return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }], }; } // Handle string operations if (jsonPath.match(/\.(toLowerCase|toUpperCase|startsWith|endsWith|contains|matches)\(/)) { const baseData = JSONPath.value(jsonData, jsonPath.split('.')[0]); const stringOp = jsonPath.slice(jsonPath.indexOf('.') + 1); const result = handleStringOperations(baseData, stringOp); return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }], }; } // Handle array transformations if (jsonPath.match(/\.(map|flatten|union|intersection)\(/)) { const baseData = Array.isArray(jsonData) ? jsonData : [jsonData]; const transformOp = jsonPath.slice(jsonPath.indexOf('.')); const result = handleArrayTransformations(baseData, transformOp); return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }], }; } // Handle grouping operations if (jsonPath.includes('.groupBy(')) { const baseData = Array.isArray(jsonData) ? jsonData : [jsonData]; const result = handleGrouping(baseData, jsonPath); return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }], }; } // Handle aggregation functions if (jsonPath.match(/\.(sum|avg|min|max)\(\w+\)/)) { const result = handleAggregation( Array.isArray(jsonData) ? jsonData : [jsonData], jsonPath ); return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }], }; } // Handle array operations (sort, distinct) if (jsonPath.includes('.sort(') || jsonPath.includes('.distinct()')) { let result = Array.isArray(jsonData) ? jsonData : [jsonData]; const operations = jsonPath.split(/(?=\.(?:sort|distinct))/); for (const op of operations) { if (op.startsWith('.sort') || op.startsWith('.distinct')) { result = handleArrayOperations(result, op); } } return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }], }; } // Handle length() function if (jsonPath === "$.length()") { return { content: [{ type: "text", text: JSON.stringify(getArrayLength(jsonData), null, 2) }], }; } // Handle complex array operations (reverse, slice) if (jsonPath.includes("-1") || jsonPath.includes(":")) { let result = Array.isArray(jsonData) ? jsonData : [jsonData]; // Split multiple operations const operations = jsonPath.match(/\[.*?\]/g) || []; for (const op of operations) { result = handleArrayOperations(result, op); } // Handle field selection if (jsonPath.includes(".")) { const fieldMatch = jsonPath.match(/\.([^.\[]+)$/); if (fieldMatch) { const field = fieldMatch[1]; result = result.map(item => item[field]); } } return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }], }; } // Handle object projection if (jsonPath.includes(".{")) { const allData = Array.isArray(jsonData) ? jsonData : [jsonData]; const projectionMatch = jsonPath.match(/\.\{(.+?)\}/); if (projectionMatch) { const fieldPairs = projectionMatch[1].split(',') .map(pair => { const [key, value] = pair.split(':').map(s => s.trim()); return { key, value: value || key }; }); const result = allData.map((item: Record<string, any>) => { const obj: Record<string, any> = {}; fieldPairs.forEach(({ key, value }) => { obj[key] = item[value]; }); return obj; }); return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }], }; } } // Default JSONPath evaluation const result = JSONPath.value(jsonData, jsonPath); return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }], }; }
  • Zod validation schema for 'query' tool input arguments (url and jsonPath). Used in handler to parse arguments.
    const QueryArgumentsSchema = z.object({ url: z.string().url(), jsonPath: z.string(), });
  • src/index.ts:406-421 (registration)
    Tool registration in the listTools response, defining name, description, and input schema for the 'query' tool.
    name: "query", description: "Query JSON data using JSONPath syntax", inputSchema: { type: "object", properties: { url: { type: "string", description: "URL of the JSON data source", }, jsonPath: { type: "string", description: "JSONPath expression (e.g. $.store.book[*].author)", } }, required: ["url", "jsonPath"], },
  • Core helper function to fetch and parse JSON data from the provided URL, used by the query handler.
    async function fetchData(url: string) { const response = await fetch(url, { headers: { 'Accept': 'application/json', 'User-Agent': 'Mozilla/5.0' } }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); return data; }

Other Tools

Related 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/GongRzhe/JSON-MCP-Server'

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