Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- [Zephyr] Added a tool for retrieving Environments [#243](https://github.com/SmartBear/smartbear-mcp/pull/243)
- [Zephyr] Added a tool for retrieving a list of Test Executions [#213](https://github.com/SmartBear/smartbear-mcp/pull/213)
- [Swagger] Added `create_api_from_prompt` tool for generating API definitions from natural language descriptions using SmartBear AI, with automatic organization governance (formerly standardization)
- [Swagger] Added `apply_api_governance` (formerly `standardize_api`) tool for scanning and automatically fixing API definitions to comply with organization governance rules using SmartBear AI
- [Swagger] Terminology update: "Standardization" is now marketed as "Governance" - both terms refer to the same feature for API validation and compliance

## [0.11.0] - 2025-11-20

Expand Down Expand Up @@ -43,13 +46,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- [Qmetry] Added 4 New QMetry tools to enhance test management capabilities [#194](https://github.com/SmartBear/smartbear-mcp/pull/194)
- [Qmetry] Implement comprehensive test case tooling with enhanced error handling [#193](https://github.com/SmartBear/smartbear-mcp/pull/193)
- [API Hub] Add `scan_api_standardization` tool for validating API definitions against organization standardization rules [#176](https://github.com/SmartBear/smartbear-mcp/pull/176)
- [API Hub] Add `scan_api_governance` (formerly `scan_api_standardization`) tool for validating API definitions against organization governance rules [#176](https://github.com/SmartBear/smartbear-mcp/pull/176)

## [0.8.0] - 2025-10-13

### Added
- [API Hub] Add `create_or_update_api` tool for creating or updating new API definitions in API Hub for Design
- [API Hub] Add `create_api_from_template` tool for creating new API definitions from templates in API Hub for Design
- [API Hub] Add `create_or_update_api` tool for creating or updating new API definitions in API Hub for Design [#257](https://github.com/SmartBear/smartbear-mcp/pull/257)
- [API Hub] Add `create_api_from_template` tool for creating new API definitions from templates in API Hub for Design [#257](https://github.com/SmartBear/smartbear-mcp/pull/257)
- [Zephyr] Add Zephyr capabilities to MCP [#171](https://github.com/SmartBear/smartbear-mcp/pull/171)

### Changed
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ See individual guides for suggested prompts and supported tools and resources:
- [Test Hub](https://developer.smartbear.com/smartbear-mcp/docs/test-hub-integration) - Test management and execution capabilities
- **Swagger**
- [Portal](https://developer.smartbear.com/smartbear-mcp/docs/swagger-portal-integration) - Portal and product management capabilities
- [Studio](https://developer.smartbear.com/smartbear-mcp/docs/swagger-studio-integration) - API and Domain management capabilities
- [Studio](https://developer.smartbear.com/smartbear-mcp/docs/swagger-studio-integration) - API and Domain management capabilities, including AI-powered API generation from prompts and automatic governance (formerly standardization)
- [Contract Testing (PactFlow)](https://developer.smartbear.com/pactflow/default/getting-started) - Contract testing capabilities
- [QMetry](https://developer.smartbear.com/smartbear-mcp/docs/qmetry-integration) - QMetry Test Management capabilities
- [Zephyr](https://developer.smartbear.com/smartbear-mcp/docs/zephyr-integration) - Zephyr Test Management capabilities
Expand Down
43 changes: 37 additions & 6 deletions docs/products/SmartBear MCP Server/swagger-studio-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,18 +64,48 @@ The Swagger Studio client provides comprehensive API and Domain management capab
| `apiName` | API name | string | Yes |
| `template` | Template name to use for creating the API. Format: owner/template-name/version (e.g., 'swagger-hub/petstore-template/1.0.0'). API is created with fixed values: private visibility, no project assignment, and reconciliation enabled.<br />**Note**: Available templates can be found in your organization's SwaggerHub template library or by checking the SwaggerHub public templates (e.g. via search_apis_and_domains). | string | Yes |

#### `scan_api_standardization`
#### `scan_api_governance` (formerly `scan_api_standardization`)

- Purpose: Run a standardization scan against an API definition using the organization's standardization configuration. Validates OpenAPI/AsyncAPI definitions against configured governance rules and style guides.
- Returns: Standardization result with a list of validation errors and warnings. Each error includes severity level, rule name, and location information.
- Purpose: Run a governance scan against an API definition using the organization's governance configuration. Validates OpenAPI/AsyncAPI definitions against configured governance rules and style guides.
- Returns: Governance scan result with a list of validation errors and warnings. Each error includes severity level, rule name, and location information.
- Use case: Validate API definitions against organization standards before publishing, ensure compliance with API governance policies, and identify design inconsistencies early in the development process.
- Note: This feature was previously called "standardization" and is now marketed as "governance". Both terms refer to the same functionality.
- Parameters:

| Parameter | Description | Type | Required |
| --- | --- | --- | --- |
| `orgName` | Organization name to use for standardization rules | string | Yes |
| `orgName` | Organization name to use for governance rules | string | Yes |
| `definition` | API definition content (OpenAPI/AsyncAPI specification in JSON or YAML format). Format is automatically detected. | string | Yes |

#### `create_api_from_prompt`

- Purpose: Generate and save an API definition based on a natural language prompt using SmartBear AI. This tool automatically applies organization governance rules during API generation. The specType parameter determines the format of the generated definition.
- Returns: API metadata including owner, name, specType, version (from X-Version header if available), SwaggerHub URL, and operation type ('create' or 'update'). HTTP 201 indicates creation, HTTP 200 indicates update.
- Use case: Rapidly create APIs from natural language descriptions (e.g., "Create a RESTful API for managing a pet store with endpoints for pets, orders, and inventory"), generate API prototypes for proof-of-concept work, or bootstrap new API projects with AI assistance while ensuring compliance with organization standards.
- Note: This tool automatically applies governance rules (previously called "standardization") during API generation.
- Parameters:

| Parameter | Description | Type | Required |
| --- | --- | --- | --- |
| `owner` | API owner (organization or user, case-sensitive) | string | Yes |
| `apiName` | API name | string | Yes |
| `prompt` | The prompt describing the desired API functionality. Be specific about resources, operations, and data models. Examples: "Create a RESTful API for managing a pet store with endpoints for pets, orders, and inventory", "Build an API for a blog platform with posts, comments, and users" | string | Yes |
| `specType` | Specification type for the generated API definition.<br />Options: `openapi20` (OpenAPI 2.0), `openapi30x` (OpenAPI 3.0.x, default), `openapi31x` (OpenAPI 3.1.x), `asyncapi2xx` (AsyncAPI 2.x), `asyncapi30x` (AsyncAPI 3.0.x)<br />Default: `openapi30x` | string | No |

#### `apply_api_governance` (formerly `standardize_api`)

- Purpose: Apply governance rules and fix an API definition using AI. Scans the API definition for governance violations and automatically fixes them using SmartBear AI. If violations are found, they will be sent to SmartBear AI to generate a corrected definition, which is then saved back to the registry.
- Returns: Governance result including a message, the number of errors found, and the fixed definition if successful. Also includes details about each error (description, line number, severity).
- Use case: Automatically fix API definitions that fail governance scans, remediate governance violations in existing APIs, or clean up imported/legacy API definitions to meet current organization standards.
- Note: This feature was previously called "standardization" and is now marketed as "governance". Both terms refer to the same functionality.
- Parameters:

| Parameter | Description | Type | Required |
| --- | --- | --- | --- |
| `owner` | API owner (organization or user, case-sensitive) | string | Yes |
| `api` | API name (case-sensitive) | string | Yes |
| `version` | Version identifier | string | Yes |

## Configuration

To use Swagger Studio tools, you need to configure the `SWAGGER_API_KEY` environment variable with your Swagger API token.
Expand All @@ -84,5 +114,6 @@ To use Swagger Studio tools, you need to configure the `SWAGGER_API_KEY` environ

1. **API Discovery**: Use `search_apis_and_domains` to find existing APIs in your Swagger Studio.
2. **API Integration**: Retrieve specific API definitions with `get_api_definition` for development or testing purposes.
3. **API Creation**: Create new APIs using `create_or_update_api` with custom definitions or `create_api_from_template` using organization templates.
4. **API Governance**: Validate API definitions against organization standards using `scan_api_standardization` to ensure compliance with governance policies.
3. **API Creation**: Create new APIs using `create_or_update_api` with custom definitions, `create_api_from_template` using organization templates, or `create_api_from_prompt` with natural language descriptions powered by AI.
4. **API Governance**: Validate API definitions against organization standards using `scan_api_governance` (formerly `scan_api_standardization`) to ensure compliance with governance policies, then use `apply_api_governance` (formerly `standardize_api`) to automatically fix any violations.
5. **AI-Powered API Development**: Leverage `create_api_from_prompt` to rapidly prototype APIs from natural language, then use `apply_api_governance` (formerly `standardize_api`) to ensure they meet your organization's standards.
16 changes: 16 additions & 0 deletions src/swagger/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import {
type ApiDefinitionParams,
type ApiSearchParams,
type ApiSearchResponse,
type CreateApiFromPromptParams,
type CreateApiFromPromptResponse,
type CreateApiFromTemplateParams,
type CreateApiFromTemplateResponse,
type CreateApiParams,
Expand All @@ -34,6 +36,8 @@ import {
type ScanStandardizationParams,
type SectionsListResponse,
type StandardizationResult,
type StandardizeApiParams,
type StandardizeApiResponse,
type SuccessResponse,
SwaggerAPI,
SwaggerConfiguration,
Expand Down Expand Up @@ -223,12 +227,24 @@ export class SwaggerClient implements Client {
return this.getApi().getOrganizations(args);
}

async createApiFromPrompt(
args: CreateApiFromPromptParams,
): Promise<CreateApiFromPromptResponse | FallbackResponse> {
return this.getApi().createApiFromPrompt(args);
}

async scanStandardization(
args: ScanStandardizationParams,
): Promise<StandardizationResult | FallbackResponse> {
return this.getApi().scanStandardization(args);
}

async standardizeApi(
args: StandardizeApiParams,
): Promise<StandardizeApiResponse | FallbackResponse> {
return this.getApi().standardizeApi(args);
}

registerTools(
register: RegisterToolsFunction,
_getInput: GetInputFunction,
Expand Down
144 changes: 136 additions & 8 deletions src/swagger/client/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,16 @@ import type {
ApiSearchResponse,
ApiSpecification,
ApisJsonResponse,
CreateApiFromPromptParams,
CreateApiFromPromptResponse,
CreateApiFromTemplateParams,
CreateApiFromTemplateResponse,
CreateApiParams,
CreateApiResponse,
ScanStandardizationParams,
StandardizationResult,
StandardizeApiParams,
StandardizeApiResponse,
} from "./registry-types.js";
import type {
OrganizationsListResponse,
Expand All @@ -52,6 +56,33 @@ import type {
const SWAGGER_URL_REGEX =
/\/(apis|domains|templates)\/([^/]+)\/([^/]+)\/([^/]+)/;

/**
* Type guard to check if a value has an 'id' property
*/
function hasId(
value: unknown,
): value is { id: string } & Record<string, unknown> {
return typeof value === "object" && value !== null && "id" in value;
}

/**
* Type guard to check if a value has a 'message' property
*/
function hasMessage(
value: unknown,
): value is { message: string } & Record<string, unknown> {
return typeof value === "object" && value !== null && "message" in value;
}

/**
* Type guard to check if a value has an 'errorsFound' property
*/
function hasErrorsFound(
value: unknown,
): value is { errorsFound: number } & Record<string, unknown> {
return typeof value === "object" && value !== null && "errorsFound" in value;
}

export class SwaggerAPI {
private config: SwaggerConfiguration;
private headers: Record<string, string>;
Expand Down Expand Up @@ -188,7 +219,7 @@ export class SwaggerAPI {
body: JSON.stringify(body),
});
const result = await this.handleResponse<Portal>(response);
if (!("id" in (result as any))) {
if (!hasId(result)) {
throw new Error("Unexpected empty response creating portal");
}
return result as Portal;
Expand All @@ -203,7 +234,7 @@ export class SwaggerAPI {
},
);
const result = await this.handleResponse<Portal>(response);
if (!("id" in (result as any))) {
if (!hasId(result)) {
throw new ToolError("Portal not found or empty response");
}
return result as Portal;
Expand Down Expand Up @@ -269,7 +300,7 @@ export class SwaggerAPI {
},
);
const result = await this.handleResponse<Product>(response);
if (!("id" in (result as any))) {
if (!hasId(result)) {
throw new Error("Unexpected empty response creating product");
}
return result as Product;
Expand All @@ -284,7 +315,7 @@ export class SwaggerAPI {
},
);
const result = await this.handleResponse<Product>(response);
if (!("id" in (result as any))) {
if (!hasId(result)) {
throw new ToolError("Product not found or empty response");
}
return result as Product;
Expand Down Expand Up @@ -738,7 +769,7 @@ export class SwaggerAPI {
owner: params.owner,
apiName: params.apiName,
version: "1.0.0",
url: `https://app.swaggerhub.com/apis/${params.owner}/${params.apiName}/1.0.0`,
url: `${this.config.uiBasePath}/apis/${params.owner}/${params.apiName}/1.0.0`,
operation,
};
}
Expand Down Expand Up @@ -782,7 +813,61 @@ export class SwaggerAPI {
owner: params.owner,
apiName: params.apiName,
template: params.template,
url: `https://app.swaggerhub.com/apis/${params.owner}/${params.apiName}`,
url: `${this.config.uiBasePath}/apis/${params.owner}/${params.apiName}`,
operation,
};
}

/**
* Create API from Prompt using SmartBear AI
* @param params Parameters for creating API from prompt including owner, api name, prompt, and specification type
* @returns Created API metadata with URL. HTTP 201 indicates creation, HTTP 200 for update, HTTP 205 for reload
*/
async createApiFromPrompt(
params: CreateApiFromPromptParams,
): Promise<CreateApiFromPromptResponse> {
// Construct the URL with query parameters
const searchParams = new URLSearchParams();
const specType = params.specType ?? "openapi30x";
searchParams.append("specType", specType);

const url = `${this.config.registryBasePath}/apis/${encodeURIComponent(
params.owner,
)}/${encodeURIComponent(params.apiName)}/.ai?${searchParams.toString()}`;

// Use POST method with JSON body containing the prompt
const response = await fetch(url, {
method: "POST",
headers: {
...this.headers,
"Content-Type": "application/json",
},
body: JSON.stringify(params.prompt),
});

if (!response.ok) {
const errorText = await response.text().catch(() => "");
throw new ToolError(
`SwaggerHub Registry API createApiFromPrompt failed - status: ${response.status} ${response.statusText}${errorText ? ` - ${errorText}` : ""}. URL: ${url}`,
);
}

// Determine operation type based on HTTP status code
// 201 = new API created, 200 = existing API updated, 205 = API saved and should be reloaded
const operation = response.status === 201 ? "create" : "update";

// Extract version from X-Version header
const version = response.headers.get("X-Version");

// Return formatted response with the required fields
return {
owner: params.owner,
apiName: params.apiName,
specType: specType,
version: version || undefined,
url: version
? `${this.config.uiBasePath}/apis/${params.owner}/${params.apiName}/${version}`
: `${this.config.uiBasePath}/apis/${params.owner}/${params.apiName}`,
operation,
};
}
Expand Down Expand Up @@ -830,7 +915,7 @@ export class SwaggerAPI {
const parsedDefinition = JSON.parse(params.definition);
requestBody = JSON.stringify(parsedDefinition);
} catch (error) {
throw new Error(
throw new ToolError(
`Invalid JSON format in definition: ${
error instanceof Error ? error.message : "Unknown error"
}`,
Expand All @@ -853,11 +938,54 @@ export class SwaggerAPI {

if (!response.ok) {
const errorText = await response.text().catch(() => "");
throw new Error(
throw new ToolError(
`SwaggerHub Registry API scanStandardization failed - status: ${response.status} ${response.statusText}${errorText ? ` - ${errorText}` : ""}. URL: ${url}`,
);
}

return await this.handleResponse<StandardizationResult>(response);
}

/**
* Standardize and fix an API definition using AI
* @param params Parameters including owner, API name, and version
* @returns Standardization response with status and fixed definition
*/
async standardizeApi(
params: StandardizeApiParams,
): Promise<StandardizeApiResponse> {
const url = `${this.config.registryBasePath}/apis/${encodeURIComponent(
params.owner,
)}/${encodeURIComponent(params.api)}/${encodeURIComponent(
params.version,
)}/standardize`;

const response = await fetch(url, {
method: "POST",
headers: this.headers,
});

if (!response.ok) {
const errorText = await response.text().catch(() => "");
throw new ToolError(
`SwaggerHub Registry API standardizeApi failed - status: ${response.status} ${response.statusText}${errorText ? ` - ${errorText}` : ""}. URL: ${url}`,
);
}

const result = await this.handleResponse<StandardizeApiResponse>(response);

// Validate that we have the expected response structure
if (!hasMessage(result)) {
throw new ToolError(
"Unexpected response format from standardizeApi endpoint",
);
}

// If errorsFound is not present, default to 0 (no errors found)
if (!hasErrorsFound(result)) {
return { ...result, errorsFound: 0 } as StandardizeApiResponse;
}

return result as StandardizeApiResponse;
}
}
Loading