Skip to main content
Glama

Windows Operations MCP

json_tools.py•9.84 kB
""" JSON Tools Module Provides utilities for working with JSON files and data, including reading, writing, validating, and manipulating JSON content with proper error handling. """ import json from pathlib import Path from typing import Any, Dict, List, Union, TypeVar, Optional from datetime import datetime from ..decorators import tool T = TypeVar('T') def read_json_file(file_path: Union[str, Path]) -> Union[Dict, List]: """ Read and parse a JSON file, returning its contents as a Python dictionary or list. Args: file_path: Path to the JSON file (as string or Path object) Returns: Union[Dict, List]: Parsed JSON data as a Python dictionary or list Raises: FileNotFoundError: If the specified file does not exist json.JSONDecodeError: If the file contains invalid JSON PermissionError: If there are insufficient permissions to read the file OSError: For other file-related errors """ try: file_path = Path(file_path) if isinstance(file_path, str) else file_path with open(file_path, 'r', encoding='utf-8') as f: return json.load(f) except json.JSONDecodeError as e: raise json.JSONDecodeError( f"Invalid JSON in file {file_path}: {str(e)}", e.doc, e.pos ) from e except FileNotFoundError: raise FileNotFoundError(f"File not found: {file_path}") except PermissionError: raise PermissionError(f"Permission denied when reading file: {file_path}") except OSError as e: raise OSError(f"Error reading file {file_path}: {str(e)}") def write_json_file( data: Any, file_path: Union[str, Path], indent: int = 2, ensure_ascii: bool = False, sort_keys: bool = False, create_dirs: bool = True ) -> None: """ Write data to a JSON file with proper error handling. Args: data: Data to be serialized to JSON file_path: Path where to save the JSON file indent: Number of spaces for indentation (use None for compact output) ensure_ascii: If False, non-ASCII characters will be output as-is sort_keys: If True, output dictionaries will be sorted by key create_dirs: If True, create parent directories if they don't exist Raises: PermissionError: If there are insufficient permissions to write to the file OSError: For other file-related errors TypeError: If the data is not JSON serializable """ try: file_path = Path(file_path) if isinstance(file_path, str) else file_path if create_dirs: file_path.parent.mkdir(parents=True, exist_ok=True) with open(file_path, 'w', encoding='utf-8') as f: json.dump( data, f, indent=indent, ensure_ascii=ensure_ascii, sort_keys=sort_keys, default=_json_serializer ) except (TypeError, ValueError) as e: raise TypeError(f"Data is not JSON serializable: {str(e)}") from e except PermissionError: raise PermissionError(f"Permission denied when writing to file: {file_path}") except OSError as e: raise OSError(f"Error writing to file {file_path}: {str(e)}") @tool( name="validate_json", description="Validate if a string is valid JSON", parameters={ "json_str": {"type": "string", "description": "String to validate as JSON"} }, returns={"type": "object", "properties": {"valid": {"type": "boolean"}}} ) def validate_json(json_str: str) -> Dict[str, Any]: """ Validate if a string is valid JSON. Args: json_str: String to validate as JSON Returns: Dict[str, Any]: Dictionary with validation result """ try: json.loads(json_str) return {"valid": True, "success": True} except json.JSONDecodeError: return {"valid": False, "success": True} def merge_json(*json_objects: Dict) -> Dict: """ Deep merge multiple JSON objects (dictionaries) together. Args: *json_objects: Variable number of dictionaries to merge Returns: Dict: A new dictionary containing the merged result Example: >>> a = {"a": 1, "b": {"x": 10}} >>> b = {"b": {"y": 20}, "c": 30} >>> merge_json(a, b) {'a': 1, 'b': {'x': 10, 'y': 20}, 'c': 30} """ result = {} for obj in json_objects: if not isinstance(obj, dict): continue for key, value in obj.items(): if key in result and isinstance(result[key], dict) and isinstance(value, dict): result[key] = merge_json(result[key], value) else: result[key] = value return result def json_to_string( data: Any, indent: int = 2, ensure_ascii: bool = False, sort_keys: bool = False ) -> str: """ Convert a Python object to a formatted JSON string. Args: data: Python object to convert to JSON indent: Number of spaces for indentation ensure_ascii: If False, non-ASCII characters will be output as-is sort_keys: If True, output dictionaries will be sorted by key Returns: str: Formatted JSON string Raises: TypeError: If the data is not JSON serializable """ try: return json.dumps( data, indent=indent, ensure_ascii=ensure_ascii, sort_keys=sort_keys, default=_json_serializer ) except (TypeError, ValueError) as e: raise TypeError(f"Data is not JSON serializable: {str(e)}") from e def _json_serializer(obj: Any) -> Any: """ Custom JSON serializer for objects not serializable by default. Args: obj: Object to serialize Returns: A JSON-serializable representation of the object Raises: TypeError: If the object type is not supported """ if isinstance(obj, (datetime,)): return obj.isoformat() elif isinstance(obj, (set, frozenset)): return list(obj) elif hasattr(obj, '__dict__'): return obj.__dict__ elif hasattr(obj, 'to_json'): return obj.to_json() else: raise TypeError(f"Object of type {obj.__class__.__name__} is not JSON serializable") # Example usage if __name__ == "__main__": # Example usage of the JSON tools try: # Example data data = { "name": "Example", "value": 42, "nested": { "items": [1, 2, 3], "active": True }, "timestamp": datetime.now() } # Write to file write_json_file(data, "example.json", indent=2) print("Data written to example.json") # Read from file loaded_data = read_json_file("example.json") print("Data loaded from file:") print(json_to_string(loaded_data, indent=2)) # Validate JSON json_str = '{"test": "value"}' print(f"Is valid JSON: {validate_json(json_str)}") # Merge JSON objects merged = merge_json( {"a": 1, "b": {"x": 10}}, {"b": {"y": 20}, "c": 30} ) print("Merged data:") print(json_to_string(merged, indent=2)) except Exception as e: print(f"Error: {str(e)}") @tool( name="format_json_string", description="Format a JSON string with proper indentation", parameters={ "json_str": {"type": "string", "description": "JSON string to format"}, "indent": {"type": "integer", "description": "Number of spaces for indentation", "default": 2}, "sort_keys": {"type": "boolean", "description": "Whether to sort dictionary keys", "default": False} }, returns={"type": "object", "properties": {"formatted": {"type": "string"}}} ) def format_json_string( json_str: str, indent: int = 2, sort_keys: bool = False ) -> Dict[str, Any]: """ Format a JSON string with proper indentation. Args: json_str: JSON string to format indent: Number of spaces for indentation sort_keys: Whether to sort dictionary keys Returns: Dict[str, Any]: Dictionary with formatted JSON """ try: parsed = json.loads(json_str) formatted = json.dumps(parsed, indent=indent, sort_keys=sort_keys, ensure_ascii=False) return {"formatted": formatted, "success": True} except json.JSONDecodeError as e: return {"error": f"Invalid JSON: {str(e)}", "success": False} def convert_to_json(data: Any, indent: Optional[int] = None) -> str: """ Convert a Python object to a JSON string. Args: data: Python object to convert indent: Number of spaces for indentation (None for compact output) Returns: JSON string representation of the data """ return json.dumps(data, indent=indent, ensure_ascii=False) def extract_json_from_text(text: str) -> List[Dict]: """ Extract JSON objects from a text string. Args: text: Text potentially containing JSON objects Returns: List of extracted JSON objects as dictionaries """ import re # Pattern to match JSON objects and arrays json_pattern = r'(\{.*?\}|\[.*?\])' results = [] for match in re.finditer(json_pattern, text, re.DOTALL): try: json_obj = json.loads(match.group(0)) results.append(json_obj) except json.JSONDecodeError: continue return results

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/sandraschi/windows-operations-mcp'

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