Skip to main content
Glama
rawr-ai

Filesystem MCP Server

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

TableJSON Schema
NameRequiredDescriptionDefault
detailedArrayTypesNoWhether to analyze all array elements for mixed types (default: false)
maxBytesYesMaximum bytes to read from the file. Must be a positive integer. Handler default: 10KB.
maxDepthYesHow deep to analyze the structure. Must be a positive integer. Handler default: 2.
pathYesPath to the JSON file to analyze

Implementation Reference

  • 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" },
  • Mapping of the json_structure tool name to its JsonStructureArgsSchema in the central toolSchemas export.
    json_structure: JsonStructureArgsSchema,
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It effectively describes key behaviors: the tool analyzes top-level keys and types, handles arrays specially, has default parameter values (10KB maxBytes, maxDepth 2), and requires path constraints ('within allowed directories'). It doesn't mention error handling or performance characteristics, but covers core operational aspects well.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is efficiently structured with four sentences: purpose, output format, use case, and parameter constraints. Each sentence adds distinct value without redundancy. It's appropriately sized for a tool with four parameters and no annotations.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with no annotations and no output schema, the description provides good coverage of what the tool does, when to use it, and key behavioral constraints. It could be more complete by explicitly describing the output format in more detail or mentioning error cases, but it's substantially complete for understanding the tool's role among its many siblings.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already fully documents all four parameters. The description mentions maxBytes and maxDepth defaults and the path constraint, but doesn't add significant semantic meaning beyond what's in the schema descriptions. This meets the baseline expectation when schema coverage is complete.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the specific action ('Get the structure of a JSON file'), the resource ('JSON file'), and the output ('mapping of key names to their corresponding data types'). It distinguishes itself from siblings like json_sample or json_query by focusing on structural analysis rather than content extraction or querying.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context for when to use this tool ('useful for understanding the shape of large JSON files without loading their entire content'), but does not explicitly mention when not to use it or name specific alternatives among the many JSON-related sibling tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

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/rawr-ai/mcp-filesystem'

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