diff --git a/src/parser/extract-tools.ts b/src/parser/extract-tools.ts index 6371623..18aec7f 100644 --- a/src/parser/extract-tools.ts +++ b/src/parser/extract-tools.ts @@ -80,8 +80,10 @@ export function extractToolsFromApi( operation.description || operation.summary || `Executes ${method.toUpperCase()} ${path}`; // Generate input schema and extract parameters - const { inputSchema, parameters, requestBodyContentType } = - generateInputSchemaAndDetails(operation); + const { inputSchema, parameters, requestBodyContentType } = generateInputSchemaAndDetails( + operation, + pathItem.parameters + ); // Extract parameter details for execution const executionParameters = parameters.map((p) => ({ name: p.name, in: p.in })); @@ -113,9 +115,13 @@ export function extractToolsFromApi( * Generates input schema and extracts parameter details from an operation * * @param operation OpenAPI operation object + * @param pathParameters Optional path-level parameters that apply to all operations in the path * @returns Input schema, parameters, and request body content type */ -export function generateInputSchemaAndDetails(operation: OpenAPIV3.OperationObject): { +export function generateInputSchemaAndDetails( + operation: OpenAPIV3.OperationObject, + pathParameters?: (OpenAPIV3.ParameterObject | OpenAPIV3.ReferenceObject)[] +): { inputSchema: JSONSchema7 | boolean; parameters: OpenAPIV3.ParameterObject[]; requestBodyContentType?: string; @@ -123,11 +129,32 @@ export function generateInputSchemaAndDetails(operation: OpenAPIV3.OperationObje const properties: { [key: string]: JSONSchema7 | boolean } = {}; const required: string[] = []; - // Process parameters - const allParameters: OpenAPIV3.ParameterObject[] = Array.isArray(operation.parameters) + // Process parameters - merge path parameters with operation parameters + const operationParameters: OpenAPIV3.ParameterObject[] = Array.isArray(operation.parameters) ? operation.parameters.map((p) => p as OpenAPIV3.ParameterObject) : []; + const pathParametersResolved: OpenAPIV3.ParameterObject[] = Array.isArray(pathParameters) + ? pathParameters.map((p) => p as OpenAPIV3.ParameterObject) + : []; + + // Combine path parameters and operation parameters + // Operation parameters override path parameters if they have the same name/location + const allParameters: OpenAPIV3.ParameterObject[] = []; + + pathParametersResolved.concat(operationParameters).forEach((param) => { + const existingIndex = allParameters.findIndex( + (pathParam) => pathParam.name === param.name && pathParam.in === param.in + ); + if (existingIndex >= 0) { + // Override path parameter with operation parameter + allParameters[existingIndex] = param; + } else { + // Add new operation parameter + allParameters.push(param); + } + }); + allParameters.forEach((param) => { if (!param.name || !param.schema) return;