Skip to main content
Glama

OpenAPI Search MCP Server

by Sheepion
ref_resolver.py5.75 kB
""" Reference resolver for OpenAPI $ref references """ from typing import Dict, Any, Set, Optional import copy class RefResolver: """ Resolves $ref references in OpenAPI documents. This class recursively resolves JSON Schema $ref references (e.g., "#/components/schemas/User") and replaces them with the actual schema definitions. """ def __init__(self, document: Dict[str, Any]): """ Initialize RefResolver with an OpenAPI document. Args: document: Complete OpenAPI document containing components/schemas or definitions """ self.document = document # OpenAPI 3.x uses components/schemas self.components = document.get('components', {}) self.schemas = self.components.get('schemas', {}) # Swagger 2.0 uses definitions self.definitions = document.get('definitions', {}) def resolve(self, obj: Any, max_depth: int = 10, _current_depth: int = 0, _resolving: Optional[Set[str]] = None) -> Any: """ Recursively resolve all $ref references in an object. Args: obj: Object to resolve (can be dict, list, or primitive) max_depth: Maximum recursion depth to prevent infinite loops _current_depth: Current recursion depth (internal use) _resolving: Set of refs currently being resolved to detect cycles (internal use) Returns: Object with all $ref references resolved """ # Initialize resolving set on first call if _resolving is None: _resolving = set() # Check depth limit if _current_depth > max_depth: return obj # Handle None and primitives if obj is None or isinstance(obj, (str, int, float, bool)): return obj # Handle lists if isinstance(obj, list): return [ self.resolve(item, max_depth, _current_depth + 1, _resolving) for item in obj ] # Handle dictionaries if isinstance(obj, dict): # Check if this is a $ref if '$ref' in obj: ref_path = obj['$ref'] schema_name = None schema_dict = None # Handle OpenAPI 3.x format: #/components/schemas/SchemaName if ref_path.startswith('#/components/schemas/'): schema_name = ref_path.split('/')[-1] schema_dict = self.schemas # Handle Swagger 2.0 format: #/definitions/SchemaName elif ref_path.startswith('#/definitions/'): schema_name = ref_path.split('/')[-1] schema_dict = self.definitions # If we found a schema reference to resolve if schema_name and schema_dict: # Detect circular reference if ref_path in _resolving: # Return a placeholder to prevent infinite recursion return { 'x-ref-circular': ref_path, 'description': f'Circular reference to {schema_name}' } # Check if schema exists if schema_name in schema_dict: # Mark this ref as being resolved _resolving.add(ref_path) # Get the schema and resolve it recursively schema = copy.deepcopy(schema_dict[schema_name]) resolved_schema = self.resolve(schema, max_depth, _current_depth + 1, _resolving) # Unmark this ref _resolving.discard(ref_path) # Merge sibling properties from the original object (OpenAPI 3.1+ compatibility) # Properties alongside $ref like description, example, nullable, etc. if isinstance(resolved_schema, dict): # Add metadata about the original reference resolved_schema['x-ref-original'] = ref_path # Merge all properties from original object except $ref itself for key, value in obj.items(): if key != '$ref' and key not in resolved_schema: # Only add if not already in resolved schema to avoid overwriting resolved_schema[key] = copy.deepcopy(value) return resolved_schema else: # Schema not found, keep the reference return obj else: # Non-schema reference (e.g., parameters, responses), keep as-is return obj # Not a $ref, recursively resolve all values result = {} for key, value in obj.items(): result[key] = self.resolve(value, max_depth, _current_depth + 1, _resolving) return result # Unknown type, return as-is return obj def resolve_operation(self, operation: Dict[str, Any]) -> Dict[str, Any]: """ Resolve all schema references in an operation object. This is a convenience method that resolves references in: - requestBody.content.*.schema - responses.*.content.*.schema - parameters[].schema Args: operation: OpenAPI operation object Returns: Operation object with all schema references resolved """ return self.resolve(copy.deepcopy(operation))

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/Sheepion/openapi-search-mcp'

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