"""OpenAPI 规范解析器。 提供从 OpenAPI/Swagger 规范文档中自动解析 API 端点并转换为自定义工具定义的功能。 """ import json from typing import Any class OpenAPIParser: """OpenAPI 规范解析器类。 解析 OpenAPI 3.0 规范文档,提取其中的 API 端点信息并转换为自定义工具定义。 Attributes: spec: OpenAPI 规范文档的字典表示。 base_url: API 服务的基础 URL。 """ def __init__(self, spec: dict): """初始化 OpenAPI 解析器。 Args: spec: OpenAPI 规范文档的字典表示,包含 servers、paths 等字段。 """ self.spec = spec # OpenAPI 规范文档内容 self.base_url = "" # API 基础 URL servers = spec.get("servers", [{}]) if servers and isinstance(servers, list): self.base_url = servers[0].get("url", "") # 获取第一个服务器 URL 作为基础地址 def parse_tools(self) -> list[dict]: """解析 OpenAPI 规范中的所有 API 端点。 遍历 paths 中的所有 HTTP 方法,将每个端点转换为工具定义。 Returns: list[dict]: 工具定义列表,每个工具包含 name、description、parameters、path、method 等信息。 """ tools = [] paths = self.spec.get("paths", {}) # 获取所有 API 路径 for path, methods in paths.items(): if not isinstance(methods, dict): continue for method, operation in methods.items(): # 只处理标准的 HTTP 方法 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: """解析单个 API 端点的详细信息。 Args: path: API 路径,如 "/users/{id}"。 method: HTTP 方法,如 "get"、"post" 等。 operation: 端点的操作定义,包含 operationId、summary、parameters 等。 Returns: dict | None: 工具定义字典,包含名称、描述、参数等信息;如果解析失败返回 None。 """ # 生成工具名称:优先使用 operationId,否则从路径生成 op_id = operation.get("operationId", "") if not op_id: op_id = f"{method}_{path.replace('/', '_').strip('_')}" # 生成工具描述:优先使用 summary,其次 description,最后使用方法和路径 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": { # 参数 Schema "type": "object", "properties": properties, "required": required, }, "path": path, # API 路径 "method": method.upper(), # HTTP 方法(大写) } def _parse_parameters(self, operation: dict) -> dict[str, Any]: """解析 API 端点的参数定义。 包括查询参数、路径参数、请求头参数和请求体参数。 Args: operation: 端点的操作定义。 Returns: dict[str, Any]: 参数属性字典,键为参数名,值为参数类型和描述。 """ props = {} # 解析 query/path/header 参数 for param in operation.get("parameters", []): if not isinstance(param, dict): continue pname = param.get("name", "") if not pname: continue schema = param.get("schema", {}) # 参数的 Schema 定义 if not isinstance(schema, dict): schema = {} props[pname] = { "type": schema.get("type", "string"), # 参数类型,默认为 string "description": param.get("description", ""), # 参数描述 } if "enum" in schema: # 如果有限定值列表 props[pname]["enum"] = schema["enum"] # 解析请求体(requestBody)中的 JSON Schema 属性 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