json_structure
Analyze the structure of JSON files by mapping top-level keys to their data types, including array element types. Use parameters to control file size and depth for efficient analysis of large JSON data within secure directories.
Instructions
Get the structure of a JSON file by analyzing its top-level keys and their types. Returns a mapping of key names to their corresponding data types (string, number, array, etc). For arrays, it also indicates the type of the first element if available. This is useful for understanding the shape of large JSON files without loading their entire content. Requires maxBytes (default 10KB) and maxDepth (default 2) parameters. The path must be within allowed directories.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| detailedArrayTypes | No | Whether to analyze all array elements for mixed types (default: false) | |
| maxBytes | Yes | Maximum bytes to read from the file. Must be a positive integer. Handler default: 10KB. | |
| maxDepth | Yes | How deep to analyze the structure. Must be a positive integer. Handler default: 2. | |
| path | Yes | Path to the JSON file to analyze |
Implementation Reference
- src/handlers/json-handlers.ts:376-468 (handler)Main handler function that reads a JSON file, analyzes its structure recursively up to maxDepth, determines types including array element types, and returns a structured representation of the JSON schema-like structure.export async function handleJsonStructure( args: unknown, allowedDirectories: string[], symlinksMap: Map<string, string>, noFollowSymlinks: boolean ) { const parsed = parseArgs(JsonStructureArgsSchema, args, 'json_structure'); const validPath = await validatePath(parsed.path, allowedDirectories, symlinksMap, noFollowSymlinks); const jsonData = await readJsonFile(validPath, parsed.maxBytes); const { maxDepth, detailedArrayTypes = false } = parsed; const effectiveMaxDepth = maxDepth ?? 2; // Default depth 2 try { // Define a type that includes our custom type strings type ValueType = 'string' | 'number' | 'boolean' | 'object' | 'array' | `array<${string}>` | 'null' | 'undefined'; /** * Analyze the type of a value, including detailed array analysis if requested */ function analyzeType(value: any, currentDepth: number = 0): { type: ValueType; structure?: Record<string, any> } { // Handle null and undefined if (value === null) return { type: 'null' }; if (value === undefined) return { type: 'undefined' }; // Handle arrays if (Array.isArray(value)) { if (value.length === 0) return { type: 'array<empty>' as ValueType }; if (detailedArrayTypes) { // Analyze all elements for mixed types const elementTypes = new Set<string>(); value.forEach(item => { const itemType = analyzeType(item, currentDepth + 1); elementTypes.add(itemType.type); }); const typeString = Array.from(elementTypes).join('|'); return { type: `array<${typeString}>` as ValueType }; } else { // Just analyze first element const firstType = analyzeType(value[0], currentDepth + 1); return { type: `array<${firstType.type}>` as ValueType }; } } // Handle objects if (isPlainObject(value)) { const type = 'object' as ValueType; // If we haven't reached depth limit and object isn't empty, analyze structure if (currentDepth < effectiveMaxDepth && !isEmpty(value)) { // Use effectiveMaxDepth const structure: Record<string, any> = {}; for (const [key, val] of Object.entries(value)) { structure[key] = analyzeType(val, currentDepth + 1); } return { type, structure }; } return { type }; } // Handle primitives if (typeof value === 'string') return { type: 'string' }; if (typeof value === 'number') return { type: 'number' }; if (typeof value === 'boolean') return { type: 'boolean' }; // Fallback return { type: typeof value as ValueType }; } // Analyze the root structure const structure = Array.isArray(jsonData) ? { type: 'array', elements: analyzeType(jsonData, 0) } : transform( jsonData, (result: Record<string, any>, value: unknown, key: string) => { result[key] = analyzeType(value, 0); }, {} as Record<string, any> ); return { content: [{ type: "text", text: JSON.stringify(structure, null, 2) }], }; } catch (error) { if (error instanceof Error) { throw new Error(`JSON structure analysis failed: ${error.message}`); } throw error; } }
- TypeBox schema defining input arguments for the json_structure tool: path to JSON file, maxBytes limit, maxDepth for analysis, and optional detailedArrayTypes flag.export const JsonStructureArgsSchema = Type.Object({ path: Type.String({ description: 'Path to the JSON file to analyze' }), maxBytes: Type.Integer({ minimum: 1, description: 'Maximum bytes to read from the file. Must be a positive integer. Handler default: 10KB.' }), maxDepth: Type.Integer({ minimum: 1, description: 'How deep to analyze the structure. Must be a positive integer. Handler default: 2.' }), detailedArrayTypes: Type.Optional(Type.Boolean({ default: false, description: 'Whether to analyze all array elements for mixed types (default: false)' })) }); export type JsonStructureArgs = Static<typeof JsonStructureArgsSchema>;
- index.ts:281-282 (registration)Registration of the json_structure tool handler in the central toolHandlers object, binding it to handleJsonStructure with server context (allowedDirectories, symlinksMap, noFollowSymlinks).json_structure: (a: unknown) => handleJsonStructure(a, allowedDirectories, symlinksMap, noFollowSymlinks),
- index.ts:327-327 (registration)Declaration of the json_structure tool in the allTools array, including its name and description.{ name: "json_structure", description: "JSON structure" },
- src/schemas/index.ts:92-92 (registration)Mapping of the json_structure tool name to its JsonStructureArgsSchema in the central toolSchemas export.json_structure: JsonStructureArgsSchema,