import json from typing import Any class OpenAPIParser: def __init__(self, spec: dict): self.spec = spec self.base_url = "" servers = spec.get("servers", [{}]) if servers and isinstance(servers, list): self.base_url = servers[0].get("url", "") def parse_tools(self) -> list[dict]: tools = [] paths = self.spec.get("paths", {}) for path, methods in paths.items(): if not isinstance(methods, dict): continue for method, operation in methods.items(): if method in ("get", "post", "put", "delete", "patch") and isinstance(operation, dict): tool = self._parse_endpoint(path, method, operation) if tool: tools.append(tool) return tools def _parse_endpoint(self, path: str, method: str, operation: dict) -> dict | None: op_id = operation.get("operationId", "") if not op_id: op_id = f"{method}_{path.replace('/', '_').strip('_')}" description = operation.get("summary") or operation.get("description") or f"{method.upper()} {path}" properties = self._parse_parameters(operation) required = [] for param in operation.get("parameters", []): if isinstance(param, dict) and param.get("required"): required.append(param["name"]) return { "name": op_id, "description": description, "parameters": { "type": "object", "properties": properties, "required": required, }, "path": path, "method": method.upper(), } def _parse_parameters(self, operation: dict) -> dict[str, Any]: props = {} for param in operation.get("parameters", []): if not isinstance(param, dict): continue pname = param.get("name", "") if not pname: continue schema = param.get("schema", {}) if not isinstance(schema, dict): schema = {} props[pname] = { "type": schema.get("type", "string"), "description": param.get("description", ""), } if "enum" in schema: props[pname]["enum"] = schema["enum"] body = ( operation.get("requestBody", {}) .get("content", {}) .get("application/json", {}) .get("schema", {}) ) if isinstance(body, dict): for name, prop in body.get("properties", {}).items(): if isinstance(prop, dict): props[name] = { "type": prop.get("type", "string"), "description": prop.get("description", ""), } return props