Merge pull request #39 from harsha-iiiv/copilot/fix-33b9d782-1c7b-44d1-89a9-adbd77a32aa8

Upgrade package to version 3.2.0 and address code quality improvements based on review feedback
This commit is contained in:
Harsha v 2025-08-24 22:03:57 -07:00 committed by GitHub
commit f29c277860
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 75 additions and 21 deletions

View File

@ -5,6 +5,41 @@ 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/), 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). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [3.2.0] - 2025-08-24
### Added
- Endpoint filtering using `x-mcp` OpenAPI extension to control which operations are exposed as MCP tools
- CLI option `--default-include` to change default behavior for endpoint inclusion
- Precedence rules for `x-mcp` extension (operation > path > root level)
- Enhanced programmatic API with `defaultInclude` option in `getToolsFromOpenApi`
### Changed
- Improved documentation with examples for endpoint filtering and OpenAPI extensions.
- Version bump to next minor release
- Updated package version to reflect accumulated features and improvements
## [3.1.4] - 2025-06-18
### Chores
- Updated the application version to 3.1.4 and ensured the CLI displays the version dynamically.
### Style
- Improved code formatting for better readability.
### Bug Fixes
- Tool names now retain their original casing during extraction.
## [3.1.3] - 2025-06-12
### Fixed
- Cannot find the package after building and the problem during the building.
## [3.1.2] - 2025-06-08 ## [3.1.2] - 2025-06-08
### Fixed ### Fixed

View File

@ -48,17 +48,17 @@ openapi-mcp-generator --input path/to/openapi.json --output path/to/output/dir -
### CLI Options ### CLI Options
| Option | Alias | Description | Default | | Option | Alias | Description | Default |
| ------------------- | ----- | ---------------------------------------------------------------------------------------- | --------------------------------- | | ------------------- | ----- | ---------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------- |
| `--input` | `-i` | Path or URL to OpenAPI specification (YAML or JSON) | **Required** | | `--input` | `-i` | Path or URL to OpenAPI specification (YAML or JSON) | **Required** |
| `--output` | `-o` | Directory to output the generated MCP project | **Required** | | `--output` | `-o` | Directory to output the generated MCP project | **Required** |
| `--server-name` | `-n` | Name of the MCP server (`package.json:name`) | OpenAPI title or `mcp-api-server` | | `--server-name` | `-n` | Name of the MCP server (`package.json:name`) | OpenAPI title or `mcp-api-server` |
| `--server-version` | `-v` | Version of the MCP server (`package.json:version`) | OpenAPI version or `1.0.0` | | `--server-version` | `-v` | Version of the MCP server (`package.json:version`) | OpenAPI version or `1.0.0` |
| `--base-url` | `-b` | Base URL for API requests. Required if OpenAPI `servers` missing or ambiguous. | Auto-detected if possible | | `--base-url` | `-b` | Base URL for API requests. Required if OpenAPI `servers` missing or ambiguous. | Auto-detected if possible |
| `--transport` | `-t` | Transport mode: `"stdio"` (default), `"web"`, or `"streamable-http"` | `"stdio"` | | `--transport` | `-t` | Transport mode: `"stdio"` (default), `"web"`, or `"streamable-http"` | `"stdio"` |
| `--port` | `-p` | Port for web-based transports | `3000` | | `--port` | `-p` | Port for web-based transports | `3000` |
| `--default-include` | | Default behavior for x-mcp filtering (true=include by default, false=exclude by default) | `true` | | `--default-include` | | Default behavior for x-mcp filtering. Accepts `true` or `false` (case-insensitive). `true` = include by default, `false` = exclude by default. | `true` |
| `--force` | | Overwrite existing files in the output directory without confirmation | `false` | | `--force` | | Overwrite existing files in the output directory without confirmation | `false` |
## 📦 Programmatic API ## 📦 Programmatic API
@ -194,7 +194,9 @@ paths:
# no x-mcp -> included by default # no x-mcp -> included by default
``` ```
This uses standard OpenAPI extensions (x-… fields). See the OpenAPI Extensions guide for details: https://swagger.io/docs/specification/v3_0/openapi-extensions/ This uses standard OpenAPI extensions (x-… fields). See the [OpenAPI Extensions guide](https://swagger.io/docs/specification/v3_0/openapi-extensions/) for details.
Note: `x-mcp` must be a boolean or the strings `"true"`/`"false"` (case-insensitive). Other values are ignored in favor of higher-precedence or default behavior.
--- ---

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{ {
"name": "openapi-mcp-generator", "name": "openapi-mcp-generator",
"version": "3.1.4", "version": "3.2.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "openapi-mcp-generator", "name": "openapi-mcp-generator",
"version": "3.1.4", "version": "3.2.0",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@apidevtools/swagger-parser": "^10.1.1", "@apidevtools/swagger-parser": "^10.1.1",

View File

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

View File

@ -80,7 +80,8 @@ export async function getToolsFromOpenApi(
} catch (error) { } catch (error) {
// Provide more context for the error // Provide more context for the error
if (error instanceof Error) { if (error instanceof Error) {
throw new Error(`Failed to extract tools from OpenAPI: ${error.message}`); // Preserve original stack/context
throw new Error(`Failed to extract tools from OpenAPI: ${error.message}`, { cause: error });
} }
throw error; throw error;
} }

View File

@ -75,7 +75,7 @@ program
) )
.option( .option(
'--default-include <boolean>', '--default-include <boolean>',
'Default behavior for x-mcp filtering (default: true = include by default, false = exclude by default)', 'Default behavior for x-mcp filtering (true|false, case-insensitive). Default: true (include by default), false = exclude by default',
(val) => { (val) => {
const parsed = normalizeBoolean(val); const parsed = normalizeBoolean(val);
if (typeof parsed === 'boolean') return parsed; if (typeof parsed === 'boolean') return parsed;
@ -83,7 +83,8 @@ program
`Invalid value for --default-include: "${val}". Expected true/false (case-insensitive). Using default: true.` `Invalid value for --default-include: "${val}". Expected true/false (case-insensitive). Using default: true.`
); );
return true; return true;
} },
true
) )
.option('--force', 'Overwrite existing files without prompting') .option('--force', 'Overwrite existing files without prompting')
.version(pkg.version) // Match package.json version .version(pkg.version) // Match package.json version

View File

@ -43,8 +43,17 @@ export function extractToolsFromApi(
continue; continue;
} }
} catch (error) { } catch (error) {
const loc = operation.operationId || `${method} ${path}`;
const extVal =
(operation as any)['x-mcp'] ?? (pathItem as any)['x-mcp'] ?? (api as any)['x-mcp'];
let extPreview: string;
try {
extPreview = JSON.stringify(extVal);
} catch {
extPreview = String(extVal);
}
console.warn( console.warn(
`Error evaluating x-mcp extension for operation ${operation.operationId || `${method} ${path}`}:`, `Error evaluating x-mcp extension for operation ${loc} (x-mcp=${extPreview}):`,
error error
); );
if (!defaultInclude) { if (!defaultInclude) {

View File

@ -29,7 +29,11 @@ export interface CliOptions {
transport?: TransportType; transport?: TransportType;
/** Server port (for web and streamable-http transports) */ /** Server port (for web and streamable-http transports) */
port?: number; port?: number;
/** Default behavior for x-mcp filtering (default: true = include by default) */ /**
* Default behavior for x-mcp filtering.
* true (default) = include by default when x-mcp is missing or invalid;
* false = exclude by default unless x-mcp explicitly enables.
*/
defaultInclude?: boolean; defaultInclude?: boolean;
} }

View File

@ -119,7 +119,9 @@ export function normalizeBoolean(value: unknown): boolean | undefined {
if (typeof value === 'boolean') return value; if (typeof value === 'boolean') return value;
if (typeof value === 'string') { if (typeof value === 'string') {
const normalized = value.trim().toLowerCase(); const normalized = value.trim().toLowerCase();
return normalized === 'true' ? true : normalized === 'false' ? false : undefined; if (['true', '1', 'yes', 'on'].includes(normalized)) return true;
if (['false', '0', 'no', 'off'].includes(normalized)) return false;
return undefined;
} }
return undefined; return undefined;
} }