Compare commits

...

3 Commits

Author SHA1 Message Date
copilot-swe-agent[bot]
d943231672 Implement BYO OpenAPIV3.Document support in getToolsFromOpenApi
Co-authored-by: harsha-iiiv <31560965+harsha-iiiv@users.noreply.github.com>
2025-08-18 04:33:51 +00:00
copilot-swe-agent[bot]
99d3ba15d2 Initial plan for BYO OpenAPIV3.Document support
Co-authored-by: harsha-iiiv <31560965+harsha-iiiv@users.noreply.github.com>
2025-08-18 04:29:37 +00:00
copilot-swe-agent[bot]
8949a0290c Initial plan 2025-08-18 04:26:56 +00:00
3 changed files with 43 additions and 9 deletions

View File

@ -22,7 +22,7 @@ This function extracts an array of tools from an OpenAPI specification.
**Parameters:** **Parameters:**
- `specPathOrUrl`: Path to a local OpenAPI spec file or URL to a remote spec - `specPathOrUrl`: Path to a local OpenAPI spec file, URL to a remote spec, or a pre-parsed OpenAPIV3.Document
- `options`: (Optional) Configuration options - `options`: (Optional) Configuration options
**Options:** **Options:**
@ -62,6 +62,17 @@ for (const tool of filteredTools) {
console.log(` Method: ${tool.method.toUpperCase()} ${tool.pathTemplate}`); console.log(` Method: ${tool.method.toUpperCase()} ${tool.pathTemplate}`);
console.log(` OperationId: ${tool.operationId}`); console.log(` OperationId: ${tool.operationId}`);
} }
// Using a pre-parsed OpenAPI document (helpful when @apidevtools/swagger-parser fails)
import { parse } from '@readme/openapi-parser';
import { OpenAPIV3 } from 'openapi-types';
const api = await parse<OpenAPIV3.Document>(
'https://problematic-api-spec.com/openapi.json',
{ dereference: { circular: true } }
);
const tools = await getToolsFromOpenApi(api);
``` ```
## Tool Definition Structure ## Tool Definition Structure

4
package-lock.json generated
View File

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

View File

@ -9,6 +9,16 @@ import { extractToolsFromApi } from './parser/extract-tools.js';
import { McpToolDefinition } from './types/index.js'; import { McpToolDefinition } from './types/index.js';
import { determineBaseUrl } from './utils/url.js'; import { determineBaseUrl } from './utils/url.js';
/**
* Type guard to check if the input is an OpenAPI document
*
* @param spec Input that could be a string or OpenAPIV3.Document
* @returns True if input is an OpenAPIV3.Document, false otherwise
*/
function isOpenApiDocument(spec: string | OpenAPIV3.Document): spec is OpenAPIV3.Document {
return typeof spec === 'object' && spec !== null && 'openapi' in spec;
}
/** /**
* Options for generating the MCP tools * Options for generating the MCP tools
*/ */
@ -29,19 +39,32 @@ export interface GetToolsOptions {
/** /**
* Get a list of tools from an OpenAPI specification * Get a list of tools from an OpenAPI specification
* *
* @param specPathOrUrl Path or URL to the OpenAPI specification * @param specPathOrUrl Path or URL to the OpenAPI specification, or a pre-parsed OpenAPI document
* @param options Options for generating the tools * @param options Options for generating the tools
* @returns Promise that resolves to an array of tool definitions * @returns Promise that resolves to an array of tool definitions
*/ */
export async function getToolsFromOpenApi( export async function getToolsFromOpenApi(
specPathOrUrl: string, specPathOrUrl: string | OpenAPIV3.Document,
options: GetToolsOptions = {} options: GetToolsOptions = {}
): Promise<McpToolDefinition[]> { ): Promise<McpToolDefinition[]> {
try { try {
// Parse the OpenAPI spec // Parse the OpenAPI spec or use the provided document
const api = options.dereference let api: OpenAPIV3.Document;
if (isOpenApiDocument(specPathOrUrl)) {
// Input is already a parsed OpenAPI document
api = specPathOrUrl;
// If dereference option is requested, apply it to the document
if (options.dereference) {
api = (await SwaggerParser.dereference(api)) as OpenAPIV3.Document;
}
} else {
// Input is a string path or URL, parse it
api = options.dereference
? ((await SwaggerParser.dereference(specPathOrUrl)) as OpenAPIV3.Document) ? ((await SwaggerParser.dereference(specPathOrUrl)) as OpenAPIV3.Document)
: ((await SwaggerParser.parse(specPathOrUrl)) as OpenAPIV3.Document); : ((await SwaggerParser.parse(specPathOrUrl)) as OpenAPIV3.Document);
}
// Extract tools from the API // Extract tools from the API
const allTools = extractToolsFromApi(api); const allTools = extractToolsFromApi(api);