Merge pull request #22 from harsha-iiiv/fix/schema-cycle-detection

feat: Enhance schema mapping with cycle protection
This commit is contained in:
Harsha v 2025-06-08 23:49:38 +05:30 committed by GitHub
commit 78c3d91ec2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 98 additions and 53 deletions

View File

@ -5,6 +5,23 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [3.1.2] - 2025-06-08
### Fixed
- Prevent stack overflow (RangeError: Maximum call stack size exceeded) when processing recursive or cyclic OpenAPI schemas (e.g., self-referencing objects).
- Added cycle detection to schema mapping, ensuring robust handling of recursive structures.
## [3.1.1] - 2025-05-26
### Added
- Introduced a new executable command-line script for easier usage in Unix-like environments.
### Changed
- Use new CLI entry point to use the new `bin/openapi-mcp-generator.js` file.
- Updated build script to ensure the new CLI file has the correct permissions.
- Refactored `index.ts` to streamline argument parsing and error handling.
## [3.1.0] - 2025-05-18
### Added
@ -18,6 +35,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Improved module structure with better exports
- Enhanced detection of module execution context
## [3.0.0] - 2025-04-26
### Added
- Streamable HTTP support for OpenAPI MCP generator, enabling efficient handling of large payloads and real-time data transfer.
- Major architectural refactor to support streaming responses and requests.
### Fixed
- Multiple bugs related to HTTP/HTTPS connection handling, stream closure, and error propagation in streaming scenarios.
- Fixed resource leak issues on server aborts and client disconnects during streaming.
### Changed
- Major version bump due to breaking changes in API and internal structures to support streaming.
- Updated documentation to reflect new streaming capabilities and usage instructions.
- Enhanced performance and robustness of HTTP/HTTPS transport layers.
## [2.0.0] - 2025-04-12
### Added

6
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "openapi-mcp-generator",
"version": "3.1.0",
"version": "3.1.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "openapi-mcp-generator",
"version": "3.1.0",
"version": "3.1.2",
"license": "MIT",
"dependencies": {
"@apidevtools/swagger-parser": "^10.1.1",
@ -14,7 +14,7 @@
"openapi-types": "^12.1.3"
},
"bin": {
"openapi-mcp-generator": "dist/index.js"
"openapi-mcp-generator": "bin/openapi-mcp-generator.js"
},
"devDependencies": {
"@types/node": "^22.15.2",

View File

@ -1,6 +1,6 @@
{
"name": "openapi-mcp-generator",
"version": "3.1.1",
"version": "3.1.2",
"description": "Generates MCP server code from OpenAPI specifications",
"license": "MIT",
"author": "Harsha",

View File

@ -72,7 +72,7 @@ program
(val) => parseInt(val, 10)
)
.option('--force', 'Overwrite existing files without prompting')
.version('3.1.1') // Match package.json version
.version('3.1.2') // Match package.json version
.action(options => {
runGenerator(options)
.catch((error) => {

View File

@ -153,13 +153,15 @@ export function generateInputSchemaAndDetails(operation: OpenAPIV3.OperationObje
}
/**
* Maps an OpenAPI schema to a JSON Schema
* Maps an OpenAPI schema to a JSON Schema with cycle protection.
*
* @param schema OpenAPI schema object or reference
* @param seen WeakSet tracking already visited schema objects
* @returns JSON Schema representation
*/
export function mapOpenApiSchemaToJsonSchema(
schema: OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject
schema: OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject,
seen: WeakSet<object> = new WeakSet()
): JSONSchema7 | boolean {
// Handle reference objects
if ('$ref' in schema) {
@ -170,6 +172,14 @@ export function mapOpenApiSchemaToJsonSchema(
// Handle boolean schemas
if (typeof schema === 'boolean') return schema;
// Detect cycles
if (seen.has(schema)) {
console.warn(`Cycle detected in schema${schema.title ? ` "${schema.title}"` : ''}, returning generic object to break recursion.`);
return { type: 'object' };
}
seen.add(schema);
try {
// Create a copy of the schema to modify
const jsonSchema: JSONSchema7 = { ...schema } as any;
@ -202,7 +212,7 @@ export function mapOpenApiSchemaToJsonSchema(
for (const [key, propSchema] of Object.entries(jsonSchema.properties)) {
if (typeof propSchema === 'object' && propSchema !== null) {
mappedProps[key] = mapOpenApiSchemaToJsonSchema(propSchema as OpenAPIV3.SchemaObject);
mappedProps[key] = mapOpenApiSchemaToJsonSchema(propSchema as OpenAPIV3.SchemaObject, seen);
} else if (typeof propSchema === 'boolean') {
mappedProps[key] = propSchema;
}
@ -218,9 +228,12 @@ export function mapOpenApiSchemaToJsonSchema(
jsonSchema.items !== null
) {
jsonSchema.items = mapOpenApiSchemaToJsonSchema(
jsonSchema.items as OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject
jsonSchema.items as OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject,
seen
);
}
return jsonSchema;
} finally {
seen.delete(schema);
}
}